22#include <zypp/base/LogTools.h>
23#include <zypp/base/Exception.h>
24#include <zypp/base/Iterator.h>
25#include <zypp/base/Gettext.h>
26#include <zypp/base/IOStream.h>
28#include <zypp-core/base/UserRequestException>
33#include <zypp/PathInfo.h>
38#include <zypp/TmpPath.h>
40#include <zypp/ExternalProgram.h>
56#include <zypp/sat/detail/PoolImpl.h>
60#include <zypp-core/base/String.h>
61#include <zypp-core/base/StringV.h>
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>
66#include <zypp-core/base/IOTools.h>
67#include <zypp-core/zyppng/rpc/rpc.h>
68#include <zypp-core/zyppng/base/private/linuxhelpers_p.h>
69#include <zypp-core/zyppng/base/EventDispatcher>
70#include <zypp-proto/target/commit.pb.h>
71#include <zypp-proto/core/envelope.pb.h>
72#include <zypp-core/zyppng/rpc/zerocopystreams.h>
79#include "tools/zypp-rpm/errorcodes.h"
80#include <rpm/rpmlog.h>
89#include <solv/repo_rpmdb.h>
90#include <solv/chksum.h>
100 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) ->
void {
101 ::solv_chksum_free( chk,
nullptr );
103 if ( ::rpm_hash_database_state( state, chk ) == 0 )
106 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
110 WAR <<
"rpm_hash_database_state failed" << endl;
130 inline void sigMultiversionSpecChanged()
148 for (
const Transaction::Step & step : steps_r )
150 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
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 );
236 class AssertMountedBase
248 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
249 execute({
"umount",
"-R",
"-l",
_mountpoint.asString() });
257 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
269 class AssertProcMounted :
private AssertMountedBase
272 AssertProcMounted( Pathname root_r )
275 if ( ! PathInfo(root_r/
"self").isDir() ) {
276 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
278 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
282 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
290 class AssertDevMounted :
private AssertMountedBase
293 AssertDevMounted( Pathname root_r )
296 if ( ! PathInfo(root_r/
"null").isChr() ) {
297 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
302 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
306 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
323 std::ifstream infile( historyFile_r.c_str() );
324 for( iostr::EachLine in( infile ); in; in.next() )
326 const char * ch( (*in).c_str() );
328 if ( *ch <
'1' ||
'9' < *ch )
330 const char * sep1 = ::strchr( ch,
'|' );
335 bool installs =
true;
336 if ( ::strncmp( sep1,
"install|", 8 ) )
338 if ( ::strncmp( sep1,
"remove |", 8 ) )
345 const char * sep2 = ::strchr( sep1,
'|' );
346 if ( !sep2 || sep1 == sep2 )
348 (*in)[sep2-ch] =
'\0';
349 IdString pkg( sep1 );
353 onSystemByUserList.erase( pkg );
357 if ( (sep1 = ::strchr( sep2+1,
'|' ))
358 && (sep1 = ::strchr( sep1+1,
'|' ))
359 && (sep2 = ::strchr( sep1+1,
'|' )) )
361 (*in)[sep2-ch] =
'\0';
362 if ( ::strchr( sep1+1,
'@' ) )
365 onSystemByUserList.insert( pkg );
370 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
371 return onSystemByUserList;
381 return PluginFrame( command_r, json::Object {
382 {
"TransactionStepList", steps_r }
392 MIL <<
"Testcases to keep: " << toKeep << endl;
398 WAR <<
"No Target no Testcase!" << endl;
402 std::string stem(
"updateTestcase" );
403 Pathname dir( target->assertRootPrefix(
"/var/log/") );
407 std::list<std::string> content;
409 std::set<std::string> cases;
410 for_( c, content.begin(), content.end() )
415 if ( cases.size() >= toKeep )
417 unsigned toDel = cases.size() - toKeep + 1;
418 for_( c, cases.begin(), cases.end() )
427 MIL <<
"Write new testcase " << next << endl;
428 getZYpp()->resolver()->createSolverTestcase( next.
asString(),
false );
445 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
455 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
460 WAR <<
"User request to abort script " << script_r << endl;
469 if ( prog.close() != 0 )
471 ret.second = report_r->problem( prog.execError() );
472 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
473 std::ostringstream sstr;
474 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
475 historylog.
comment(sstr.str(),
true);
487 bool executeScript(
const Pathname & root_r,
488 const Pathname & script_r,
489 callback::SendReport<PatchScriptReport> & report_r )
494 action = doExecuteScript( root_r, script_r, report_r );
498 switch ( action.second )
501 WAR <<
"User request to abort at script " << script_r << endl;
506 WAR <<
"User request to skip script " << script_r << endl;
516 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
525 bool RunUpdateScripts(
const Pathname & root_r,
526 const Pathname & scriptsPath_r,
527 const std::vector<sat::Solvable> & checkPackages_r,
530 if ( checkPackages_r.empty() )
533 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
535 if ( ! PathInfo( scriptsDir ).isDir() )
538 std::list<std::string> scripts;
540 if ( scripts.empty() )
548 std::map<std::string, Pathname> unify;
549 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
551 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
552 for_( sit, scripts.begin(), scripts.end() )
557 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
560 PathInfo script( scriptsDir / *sit );
561 Pathname localPath( scriptsPath_r/(*sit) );
562 std::string unifytag;
564 if ( script.isFile() )
570 else if ( ! script.isExist() )
578 if ( unifytag.empty() )
582 if ( unify[unifytag].empty() )
584 unify[unifytag] = localPath;
591 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
592 MIL <<
"Skip update script: " << msg << endl;
593 HistoryLog().comment( msg,
true );
597 if ( abort || aborting_r )
599 WAR <<
"Aborting: Skip update script " << *sit << endl;
600 HistoryLog().comment(
601 localPath.asString() +
_(
" execution skipped while aborting"),
606 MIL <<
"Found update script " << *sit << endl;
607 callback::SendReport<PatchScriptReport> report;
608 report->start( make<Package>( *it ), script.path() );
610 if ( ! executeScript( root_r, localPath, report ) )
622 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
624 std::ifstream infile( file_r.c_str() );
625 for( iostr::EachLine in( infile ); in; in.next() )
627 out_r << *in << endl;
631 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
633 std::string ret( cmd_r );
634#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
635 SUBST_IF(
"%p", notification_r.solvable().asString() );
636 SUBST_IF(
"%P", notification_r.file().asString() );
641 void sendNotification(
const Pathname & root_r,
644 if ( notifications_r.empty() )
648 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
649 if ( cmdspec.empty() )
652 std::string::size_type pos( cmdspec.find(
'|' ) );
653 if ( pos == std::string::npos )
655 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
656 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
661 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
663 enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
664 Format format = UNKNOWN;
665 if ( formatStr ==
"none" )
667 else if ( formatStr ==
"single" )
669 else if ( formatStr ==
"digest" )
671 else if ( formatStr ==
"bulk" )
675 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
676 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
684 if ( format == NONE || format == SINGLE )
686 for_( it, notifications_r.begin(), notifications_r.end() )
688 std::vector<std::string> command;
689 if ( format == SINGLE )
691 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
696 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
700 int ret = prog.close();
703 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
704 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
710 else if ( format == DIGEST || format == BULK )
712 filesystem::TmpFile tmpfile;
713 std::ofstream out( tmpfile.path().c_str() );
714 for_( it, notifications_r.begin(), notifications_r.end() )
716 if ( format == DIGEST )
718 out << it->file() << endl;
720 else if ( format == BULK )
726 std::vector<std::string> command;
727 command.push_back(
"<"+tmpfile.path().asString() );
728 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
733 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
737 int ret = prog.close();
740 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
741 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
748 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
749 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
760 void RunUpdateMessages(
const Pathname & root_r,
761 const Pathname & messagesPath_r,
762 const std::vector<sat::Solvable> & checkPackages_r,
763 ZYppCommitResult & result_r )
765 if ( checkPackages_r.empty() )
768 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
770 if ( ! PathInfo( messagesDir ).isDir() )
773 std::list<std::string> messages;
775 if ( messages.empty() )
781 HistoryLog historylog;
782 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
784 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
785 for_( sit, messages.begin(), messages.end() )
790 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
793 PathInfo message( messagesDir / *sit );
794 if ( ! message.isFile() || message.size() == 0 )
797 MIL <<
"Found update message " << *sit << endl;
798 Pathname localPath( messagesPath_r/(*sit) );
799 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
800 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
803 sendNotification( root_r, result_r.updateMessages() );
809 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
812 if ( changedPseudoInstalled.empty() )
820 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
826 HistoryLog historylog;
827 for (
const auto & el : changedPseudoInstalled )
828 historylog.patchStateChange( el.first, el.second );
837 const std::vector<sat::Solvable> & checkPackages_r,
839 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
852 , _requestedLocalesFile( home() /
"RequestedLocales" )
853 , _autoInstalledFile( home() /
"AutoInstalled" )
862 sigMultiversionSpecChanged();
863 MIL <<
"Initialized target on " <<
_root << endl;
871 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
881 boost::function<
bool ()> condition,
882 boost::function<std::string ()> value )
884 std::string val = value();
892 MIL <<
"updating '" << filename <<
"' content." << endl;
896 std::ofstream filestr;
899 filestr.open( filename.
c_str() );
901 if ( filestr.good() )
937 WAR <<
"Can't create anonymous id file" << endl;
946 Pathname flavorpath(
home() /
"LastDistributionFlavor");
952 WAR <<
"No base product, I won't create flavor cache" << endl;
956 std::string flavor = p->flavor();
968 WAR <<
"Can't create flavor cache" << endl;
981 sigMultiversionSpecChanged();
982 MIL <<
"Closed target on " <<
_root << endl;
1006 Pathname rpmsolvcookie = base/
"cookie";
1008 bool build_rpm_solv =
true;
1018 MIL <<
"Read cookie: " << cookie << endl;
1023 if ( status == rpmstatus )
1024 build_rpm_solv =
false;
1025 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
1026 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
1030 if ( build_rpm_solv )
1044 bool switchingToTmpSolvfile =
false;
1045 Exception ex(
"Failed to cache rpm database.");
1051 rpmsolv = base/
"solv";
1052 rpmsolvcookie = base/
"cookie";
1059 WAR <<
"Using a temporary solv file at " << base << endl;
1060 switchingToTmpSolvfile =
true;
1069 if ( ! switchingToTmpSolvfile )
1079 cmd.push_back(
"rpmdb2solv" );
1081 cmd.push_back(
"-r" );
1084 cmd.push_back(
"-D" );
1085 cmd.push_back(
rpm().dbPath().asString() );
1086 cmd.push_back(
"-X" );
1088 cmd.push_back(
"-p" );
1091 if ( ! oldSolvFile.
empty() )
1092 cmd.push_back( oldSolvFile.
asString() );
1094 cmd.push_back(
"-o" );
1098 std::string errdetail;
1101 WAR <<
" " << output;
1102 if ( errdetail.empty() ) {
1106 errdetail += output;
1109 int ret = prog.
close();
1130 if (
root() ==
"/" )
1141 if ( !
PathInfo(base/
"solv.idx").isExist() )
1144 return build_rpm_solv;
1162 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1163 ", force loading: " << (force?
"true":
"false") << endl;
1168 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1175 if ( newCache || force )
1192 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1198 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1223 if (
PathInfo( historyFile ).isExist() )
1230 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1231 onSystemByAuto.insert( ident );
1252 if (
PathInfo( needrebootFile ).isFile() )
1253 needrebootSpec.
parseFrom( needrebootFile );
1256 if (
PathInfo( needrebootDir ).isDir() )
1261 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1263 if ( ! isRpmConfigBackup( str_r ) )
1265 Pathname needrebootFile { needrebootDir / str_r };
1266 if (
PathInfo( needrebootFile ).isFile() )
1267 needrebootSpec.
parseFrom( needrebootFile );
1278 if ( ! hardLocks.empty() )
1287 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1299 bool explicitDryRun = policy_r.
dryRun();
1309 if (
root() ==
"/" )
1323 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1342 steps.push_back( *it );
1349 MIL <<
"Todo: " << result << endl;
1359 if ( commitPlugins )
1360 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1367 if ( ! policy_r.
dryRun() )
1373 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1380 if ( ! policy_r.
dryRun() )
1402 DBG <<
"dryRun: Not storing non-package data." << endl;
1409 if ( ! policy_r.
dryRun() )
1411 for_( it, steps.begin(), steps.end() )
1413 if ( ! it->satSolvable().isKind<
Patch>() )
1421 if ( ! patch ||patch->message().empty() )
1424 MIL <<
"Show message for " << patch << endl;
1426 if ( ! report->show( patch ) )
1428 WAR <<
"commit aborted by the user" << endl;
1435 DBG <<
"dryRun: Not checking patch messages." << endl;
1457 for_( it, steps.begin(), steps.end() )
1459 switch ( it->stepType() )
1478 localfile = packageCache.
get( pi );
1481 catch (
const AbortRequestException & exp )
1485 WAR <<
"commit cache preload aborted by the user" << endl;
1489 catch (
const SkipRequestException & exp )
1494 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1504 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1514 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1518 if ( ! policy_r.
dryRun() )
1525 commit( policy_r, packageCache, result );
1530 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1531 if ( explicitDryRun ) {
1545 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1546 if ( explicitDryRun ) {
1558 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1567 if ( commitPlugins )
1568 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1573 if ( ! policy_r.
dryRun() )
1578 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1589 struct NotifyAttemptToModify
1594 {
if ( _guard ) {
_result.attemptToModify(
true );
_guard =
false; } }
1607 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1612 NotifyAttemptToModify attemptToModify( result_r );
1617 AssertProcMounted assertProcMounted(
_root );
1618 AssertDevMounted assertDevMounted(
_root );
1621 std::vector<sat::Solvable> successfullyInstalledPackages;
1624 for_( step, steps.begin(), steps.end() )
1646 localfile = packageCache_r.
get( citem );
1648 catch (
const AbortRequestException &e )
1650 WAR <<
"commit aborted by the user" << endl;
1655 catch (
const SkipRequestException &e )
1658 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1667 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1676 bool success =
false;
1702 WAR <<
"commit aborted by the user" << endl;
1711 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1727 WAR <<
"dry run failed" << endl;
1734 WAR <<
"commit aborted by the user" << endl;
1739 WAR <<
"Install failed" << endl;
1745 if ( success && !policy_r.
dryRun() )
1748 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1757 bool success =
false;
1770 WAR <<
"commit aborted by the user" << endl;
1786 WAR <<
"commit aborted by the user" << endl;
1792 WAR <<
"removal of " << p <<
" failed";
1795 if ( success && !policy_r.
dryRun() )
1802 else if ( ! policy_r.
dryRun() )
1806 if ( ! citem.
buddy() )
1813 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1819 std::string referenceFilename( p->referenceFilename() );
1820 if ( referenceFilename.empty() )
1822 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1826 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1827 if ( !
rpm().hasFile( referencePath.asString() ) )
1832 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1836 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1865 if ( ! successfullyInstalledPackages.empty() )
1868 successfullyInstalledPackages, abort ) )
1870 WAR <<
"Commit aborted by the user" << endl;
1876 successfullyInstalledPackages,
1883 logPatchStatusChanges( result_r.
transaction(), *
this );
1902 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
1905 data.
set(
"line", std::cref(line_r) );
1906 data.set(
"level", level_r );
1912 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
1913 switch ( rpmlevel_r ) {
1914 case RPMLOG_EMERG: [[fallthrough]];
1915 case RPMLOG_ALERT: [[fallthrough]];
1917 return ReportType::loglevel::crt;
1919 return ReportType::loglevel::err;
1920 case RPMLOG_WARNING:
1921 return ReportType::loglevel::war;
1922 default: [[fallthrough]];
1923 case RPMLOG_NOTICE: [[fallthrough]];
1925 return ReportType::loglevel::msg;
1927 return ReportType::loglevel::dbg;
1935 { (*this)->report( userData_r ); }
1948 namespace zpt = zypp::proto::target;
1954 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1959 NotifyAttemptToModify attemptToModify( result_r );
1965 AssertProcMounted assertProcMounted(
_root );
1966 AssertDevMounted assertDevMounted(
_root );
1981 commit.set_flags( flags );
1984 commit.set_dbpath(
rpm().dbPath().asString() );
1990 for (
auto &[
_, value] : data ) {
1992 value.resetDispose();
1998 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
1999 auto &step = steps[stepId];
2016 locCache.value()[stepId] = packageCache_r.
get( citem );
2018 zpt::TransactionStep tStep;
2019 tStep.set_stepid( stepId );
2020 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
2021 tStep.mutable_install()->set_multiversion( p->multiversionInstall() );
2023 *
commit.mutable_steps()->Add( ) = std::move(tStep);
2025 catch (
const AbortRequestException &e )
2027 WAR <<
"commit aborted by the user" << endl;
2032 catch (
const SkipRequestException &e )
2035 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2044 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2050 zpt::TransactionStep tStep;
2051 tStep.set_stepid( stepId );
2052 tStep.mutable_remove()->set_name( p->name() );
2053 tStep.mutable_remove()->set_version( p->edition().version() );
2054 tStep.mutable_remove()->set_release( p->edition().release() );
2055 tStep.mutable_remove()->set_arch( p->arch().asString() );
2057 *
commit.mutable_steps()->Add() = std::move(tStep);
2068 zpt::TransactionStep tStep;
2069 tStep.set_stepid( stepId );
2070 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
2071 tStep.mutable_install()->set_multiversion(
false );
2072 *
commit.mutable_steps()->Add() = std::move(tStep);
2076 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2083 std::vector<sat::Solvable> successfullyInstalledPackages;
2085 if (
commit.steps_size() ) {
2088 auto loop = zyppng::EventLoop::create();
2092 const std::vector<int> interceptedSignals {
2099 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2100 unixSignals->sigReceived ().connect ([](
int signum ){
2102 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 );
2104 for(
const auto &sig : interceptedSignals )
2105 unixSignals->addSignal ( sig );
2108 for(
const auto &sig : interceptedSignals )
2109 unixSignals->removeSignal ( sig );
2116 int currentStepId = -1;
2122 bool gotEndOfScript =
false;
2125 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2126 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2127 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2128 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2129 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2132 std::optional<zpt::TransactionError> transactionError;
2135 std::string currentScriptType;
2136 std::string currentScriptPackage;
2146 unsigned lineno = 0;
2149 auto msgSource = zyppng::AsyncDataSource::create();
2150 auto scriptSource = zyppng::AsyncDataSource::create();
2155 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2157 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2159 if ( currentStepId >= 0 )
2160 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2161 cmdout.
set(
"line", line );
2165 if ( installreport ) {
2167 }
else if ( uninstallreport ) {
2169 }
else if ( scriptreport ) {
2171 }
else if ( transactionreport ) {
2173 }
else if ( cleanupreport ) {
2176 WAR <<
"Got rpm output without active report " << line;
2181 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2185 if ( line.back() !=
'\n' )
2191 const auto &processDataFromScriptFd = [&](){
2193 while ( scriptSource->canReadLine() ) {
2195 if ( gotEndOfScript )
2198 std::string l = scriptSource->readLine().asString();
2200 gotEndOfScript =
true;
2201 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2204 l = l.substr( 0, rawsize );
2206 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2207 sendRpmLineToReport( l );
2210 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2213 const auto &waitForScriptEnd = [&]() {
2216 if ( gotEndOfScript )
2220 processDataFromScriptFd();
2223 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2226 scriptSource->waitForReadyRead( 100 );
2230 const auto &aboutToStartNewReport = [&](){
2232 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2233 ERR <<
"There is still a running report, this is a bug" << std::endl;
2237 gotEndOfScript =
false;
2240 const auto &writeRpmMsgToHistory = [&](){
2241 if ( rpmmsg.size() == 0 )
2245 rpmmsg +=
"[truncated]\n";
2247 std::ostringstream sstr;
2248 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2253 const auto &finalizeCurrentReport = [&]() {
2256 if ( currentStepId >= 0 ) {
2257 step = &steps.at(currentStepId);
2261 if ( installreport ) {
2269 writeRpmMsgToHistory();
2273 ( *installreport)->progress( 100, resObj );
2276 if ( currentStepId >= 0 )
2277 locCache.value().erase( currentStepId );
2278 successfullyInstalledPackages.push_back( step->
satSolvable() );
2284 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2296 writeRpmMsgToHistory();
2299 if ( uninstallreport ) {
2307 writeRpmMsgToHistory();
2311 ( *uninstallreport)->progress( 100, resObj );
2321 writeRpmMsgToHistory();
2324 if ( scriptreport ) {
2326 ( *scriptreport)->progress( 100, resObj );
2329 if ( transactionreport ) {
2331 ( *transactionreport)->progress( 100 );
2334 if ( cleanupreport ) {
2336 ( *cleanupreport)->progress( 100 );
2342 currentScriptType.clear();
2343 currentScriptPackage.clear();
2344 installreport.reset();
2345 uninstallreport.reset();
2346 scriptreport.reset();
2347 transactionreport.reset();
2348 cleanupreport.reset();
2358 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2360 const char *argv[] = {
2363 zyppRpmBinary.data(),
2366 auto prog = zyppng::Process::create();
2370 auto messagePipe = zyppng::Pipe::create();
2376 auto scriptPipe = zyppng::Pipe::create();
2380 prog->addFd( messagePipe->writeFd );
2381 prog->addFd( scriptPipe->writeFd );
2384 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2387 prog->sigStarted().connect( [&](){
2390 messagePipe->unrefWrite();
2391 scriptPipe->unrefWrite();
2394 prog->connectFunc( &zyppng::IODevice::sigChannelReadyRead, [&](
int channel ){
2395 while( prog->canReadLine( channel ) ) {
2396 L_ERR(
"zypp-rpm") << ( channel == zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2402 const auto outFd = prog->stdinFd();
2409 zyppng::rpc::HeaderSizeType msgSize =
commit.ByteSizeLong();
2410 const auto written = zyppng::eintrSafeCall( ::write, outFd, &msgSize,
sizeof(zyppng::rpc::HeaderSizeType) );
2411 if ( written !=
sizeof(zyppng::rpc::HeaderSizeType) ) {
2412 prog->stop( SIGKILL );
2416 zyppng::FileOutputStream fo ( outFd );
2417 if ( !
commit.SerializeToZeroCopyStream( &fo ) ) {
2418 prog->stop( SIGKILL );
2428 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd } ) )
2431 zyppng::rpc::HeaderSizeType pendingMessageSize = 0;
2432 const auto &processMessages = [&] ( ) {
2436 const auto &parseMsgWithStepId = [&steps](
const auto &m,
auto &p ){
2437 if ( !p.ParseFromString( m.value() ) ) {
2438 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2442 auto id = p.stepid();
2443 if ( id < 0 || id >= steps.size() ) {
2444 ERR <<
"Received invalid stepId: " <<
id <<
" in " << m.messagetypename() <<
" message from zypp-rpm, ignoring." << std::endl;
2450 while ( msgSource->bytesAvailable() ) {
2452 if ( pendingMessageSize == 0 ) {
2453 if ( std::size_t(msgSource->bytesAvailable()) >=
sizeof( zyppng::rpc::HeaderSizeType ) ) {
2454 msgSource->read(
reinterpret_cast<char *
>( &pendingMessageSize ),
sizeof( zyppng::rpc::HeaderSizeType ) );
2458 if ( msgSource->bytesAvailable() < pendingMessageSize ) {
2462 auto bytes = msgSource->read( pendingMessageSize );
2463 pendingMessageSize = 0;
2465 zypp::proto::Envelope m;
2466 if (! m.ParseFromArray( bytes.data(), bytes.size() ) ) {
2469 ERR <<
"Received misformed message from zypp-rpm, ignoring" << std::endl;
2477 const auto &mName = m.messagetypename();
2478 if ( mName ==
"zypp.proto.target.RpmLog" ) {
2481 if ( !p.ParseFromString( m.value() ) ) {
2482 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2485 ( p.level() >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2486 : p.level() >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2487 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p.level() <<
"> " << p.line();
2490 }
else if ( mName ==
"zypp.proto.target.PackageBegin" ) {
2491 finalizeCurrentReport();
2493 zpt::PackageBegin p;
2494 if ( !parseMsgWithStepId( m, p ) )
2497 aboutToStartNewReport();
2499 auto & step = steps.at( p.stepid() );
2500 currentStepId = p.stepid();
2502 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2503 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2505 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2506 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2509 }
else if ( mName ==
"zypp.proto.target.PackageFinished" ) {
2510 zpt::PackageFinished p;
2511 if ( !parseMsgWithStepId( m, p ) )
2514 if ( p.stepid() < 0 || p.stepid() > steps.size() )
2521 }
else if ( mName ==
"zypp.proto.target.PackageProgress" ) {
2522 zpt::PackageProgress p;
2523 if ( !parseMsgWithStepId( m, p ) )
2526 if ( uninstallreport )
2527 (*uninstallreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2528 else if ( installreport )
2529 (*installreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2531 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2533 }
else if ( mName ==
"zypp.proto.target.PackageError" ) {
2534 zpt::PackageError p;
2535 if ( !parseMsgWithStepId( m, p ) )
2538 if ( p.stepid() >= 0 && p.stepid() < steps.size() )
2541 finalizeCurrentReport();
2543 }
else if ( mName ==
"zypp.proto.target.ScriptBegin" ) {
2544 finalizeCurrentReport();
2547 if ( !p.ParseFromString( m.value() ) ) {
2548 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2552 aboutToStartNewReport();
2555 const auto stepId = p.stepid();
2556 if ( stepId >= 0 && stepId < steps.size() ) {
2560 currentStepId = p.stepid();
2561 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2562 currentScriptType = p.scripttype();
2563 currentScriptPackage = p.scriptpackage();
2564 (*scriptreport)->start( p.scripttype(), p.scriptpackage(), resPtr );
2566 }
else if ( mName ==
"zypp.proto.target.ScriptFinished" ) {
2570 }
else if ( mName ==
"zypp.proto.target.ScriptError" ) {
2573 if ( !p.ParseFromString( m.value() ) ) {
2574 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2579 const auto stepId = p.stepid();
2580 if ( stepId >= 0 && stepId < steps.size() ) {
2590 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2593 writeRpmMsgToHistory();
2595 if ( !scriptreport ) {
2596 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2605 scriptreport.reset();
2608 }
else if ( mName ==
"zypp.proto.target.CleanupBegin" ) {
2609 finalizeCurrentReport();
2611 zpt::CleanupBegin beg;
2612 if ( !beg.ParseFromString( m.value() ) ) {
2613 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2617 aboutToStartNewReport();
2618 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2619 (*cleanupreport)->start( beg.nvra() );
2620 }
else if ( mName ==
"zypp.proto.target.CleanupFinished" ) {
2622 finalizeCurrentReport();
2624 }
else if ( mName ==
"zypp.proto.target.CleanupProgress" ) {
2625 zpt::CleanupProgress prog;
2626 if ( !prog.ParseFromString( m.value() ) ) {
2627 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2631 if ( !cleanupreport ) {
2632 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2636 (*cleanupreport)->progress( prog.amount() );
2638 }
else if ( mName ==
"zypp.proto.target.TransBegin" ) {
2639 finalizeCurrentReport();
2641 zpt::TransBegin beg;
2642 if ( !beg.ParseFromString( m.value() ) ) {
2643 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2647 aboutToStartNewReport();
2648 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2649 (*transactionreport)->start( beg.name() );
2650 }
else if ( mName ==
"zypp.proto.target.TransFinished" ) {
2652 finalizeCurrentReport();
2654 }
else if ( mName ==
"zypp.proto.target.TransProgress" ) {
2655 zpt::TransProgress prog;
2656 if ( !prog.ParseFromString( m.value() ) ) {
2657 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2661 if ( !transactionreport ) {
2662 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2666 (*transactionreport)->progress( prog.amount() );
2667 }
else if ( mName ==
"zypp.proto.target.TransactionError" ) {
2669 zpt::TransactionError error;
2670 if ( !error.ParseFromString( m.value() ) ) {
2671 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2676 transactionError = std::move(error);
2679 ERR <<
"Received unexpected message from zypp-rpm: "<< m.messagetypename() <<
", ignoring" << std::endl;
2685 msgSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, processMessages );
2688 int zyppRpmExitCode = -1;
2689 prog->connectFunc( &zyppng::Process::sigFinished, [&](
int code ){
2690 zyppRpmExitCode = code;
2694 if ( !prog->start( argv ) ) {
2705 finalizeCurrentReport();
2708 bool readMsgs =
false;
2709 while( prog->canReadLine( zyppng::Process::StdErr ) ) {
2711 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdErr ).asStringView();
2713 while( prog->canReadLine( zyppng::Process::StdOut ) ) {
2715 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdOut ).asStringView();
2718 while ( scriptSource->canReadLine() ) {
2720 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2722 if ( scriptSource->bytesAvailable() > 0 ) {
2724 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2729 switch ( zyppRpmExitCode ) {
2731 case zypprpm::NoError:
2732 case zypprpm::RpmFinishedWithError:
2734 case zypprpm::RpmFinishedWithTransactionError: {
2736 if ( transactionError ) {
2738 std::ostringstream sstr;
2739 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2740 for (
const auto & err : transactionError->problems() ) {
2741 sstr <<
" " << err.message() <<
"\n";
2751 case zypprpm::FailedToOpenDb:
2754 case zypprpm::WrongHeaderSize:
2755 case zypprpm::WrongMessageFormat:
2758 case zypprpm::RpmInitFailed:
2761 case zypprpm::FailedToReadPackage:
2764 case zypprpm::FailedToAddStepToTransaction:
2767 case zypprpm::RpmOrderFailed:
2770 case zypprpm::FailedToCreateLock:
2775 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2776 auto &step = steps[stepId];
2788 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2792 std::string referenceFilename( p->referenceFilename() );
2794 if ( referenceFilename.empty() ) {
2795 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2797 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2799 if ( !
rpm().hasFile( referencePath.asString() ) ) {
2803 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2805 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2819 if ( ! successfullyInstalledPackages.empty() )
2822 successfullyInstalledPackages, abort ) )
2824 WAR <<
"Commit aborted by the user" << endl;
2830 successfullyInstalledPackages,
2837 logPatchStatusChanges( result_r.
transaction(), *
this );
2865 if ( baseproduct.isFile() )
2878 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2883 inline Pathname staticGuessRoot(
const Pathname & root_r )
2885 if ( root_r.empty() )
2890 return Pathname(
"/");
2896 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2898 std::ifstream idfile( file_r.c_str() );
2899 for( iostr::EachLine in( idfile ); in; in.next() )
2902 if ( ! line.empty() )
2905 return std::string();
2916 if ( p->isTargetDistribution() )
2924 const Pathname needroot( staticGuessRoot(root_r) );
2925 const Target_constPtr target( getZYpp()->getTarget() );
2926 if ( target && target->root() == needroot )
2927 return target->requestedLocales();
2933 MIL <<
"updateAutoInstalled if changed..." << endl;
2941 {
return baseproductdata(
_root ).registerTarget(); }
2944 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
2947 {
return baseproductdata(
_root ).registerRelease(); }
2950 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
2953 {
return baseproductdata(
_root ).registerFlavor(); }
2956 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
2989 std::string
distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version();
2996 scoped_ptr<rpm::RpmDb> tmprpmdb;
3002 tmprpmdb->initDatabase( );
3019 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3024 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3030 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3033 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3034 if ( ret.
empty() && root_r !=
"/" )
3037 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3045 return guessAnonymousUniqueId(
root() );
3050 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3057 MIL <<
"New VendorAttr: " << vendorAttr_r << 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...
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
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]
unsigned epoch_t
Type of an epoch.
std::string version() const
Version.
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 ...
const std::string & command() const
The command we're executing.
std::vector< std::string > Arguments
int close()
Wait for the progamm to complete.
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.
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
Command frame for communication with PluginScript.
Combining sat::Solvable and ResStatus.
ResObject::constPtr resolvable() const
Returns the ResObject::constPtr.
ResStatus & status() const
Returns the current status.
sat::Solvable buddy() const
Return the buddy we share our status object with.
TraitsType::constPtrType constPtr
Track changing files or directories.
static RepoStatus fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
void saveToCookieFile(const Pathname &path_r) const
Save the status information to a cookie file.
bool solvablesEmpty() const
Whether Repository contains solvables.
SolvableIterator solvablesEnd() const
Iterator behind the last Solvable.
SolvableIterator solvablesBegin() const
Iterator to the first Solvable.
size_type solvablesSize() const
Number of solvables in Repository.
void addSolv(const Pathname &file_r)
Load Solvables from a solv-file.
void eraseFromPool()
Remove this Repository from its Pool.
ChangedPseudoInstalled changedPseudoInstalled() const
Return all pseudo installed items whose current state differs from the established one.
static ResPool instance()
Singleton ctor.
EstablishedStates::ChangedPseudoInstalled ChangedPseudoInstalled
Map holding pseudo installed items where current and established status differ.
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.
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).
Definition of vendor equivalence.
Interim helper class to collect global options and settings.
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.
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).
zypp::ContentType ContentType
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.
Define a set of Solvables by ident and provides.
void addProvides(Capability provides_r)
A all sat::Solvable matching this provides_r.
void parseFrom(const InputStream &istr_r)
Parse file istr_r and add its specs (one per line, #-comments).
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
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.
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.
std::list< PoolItem > PoolItemList
list of pool items
rpm::RpmDb _rpm
RPM database.
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.
virtual ~TargetImpl()
Dtor.
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.
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
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 database content.
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
int unlink(const Pathname &path)
Like 'unlink'.
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
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 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 readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
int touch(const Pathname &path)
Change file's modification and access times.
std::string md5sum(const Pathname &file)
Compute a files md5sum.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
BlockingMode setFDBlocking(int fd, bool mode)
std::string getline(std::istream &str)
Read one line from stream.
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.
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.
std::string toLower(const std::string &s)
Return lowercase version of s.
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t", bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
std::string trim(const std::string &s, const Trim trim_r)
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
std::string rpmDbStateHash(const Pathname &root_r)
void writeUpgradeTestcase()
static bool fileMissing(const Pathname &pathname)
helper functor
void updateFileContent(const Pathname &filename, boost::function< bool()> condition, boost::function< std::string()> value)
updates the content of filename if condition is true, setting the content the the value returned by v...
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
static std::string generateRandomId()
generates a random id using uuidgen
Easy-to use interface to the ZYPP dependency resolver.
std::unordered_set< Locale > LocaleSet
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
std::list< UpdateNotificationFile > UpdateNotifications
@ 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 error(const std::string &msg_r, const UserData &userData_r=UserData())
send error 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.
bool isKind(const ResKind &kind_r) const
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.
static const UserData::ContentType contentRpmout
"zypp-rpm/cleanupkgsa": Additional rpm output (sent immediately).
static const UserData::ContentType contentRpmout
"zypp-rpm/scriptsa": Additional rpm output (sent immediately).
static const UserData::ContentType contentRpmout
"zypp-rpm/installpkgsa": Additional rpm output (sent immediately).
@ RPM_NODEPS_FORCE
only this one used
static const UserData::ContentType contentRpmout
"zypp-rpm/removepkgsa": Additional rpm output (sent immediately).
static const UserData::ContentType contentLogline
"zypp-rpm/logline" report a line suitable to be written to the screen.
static const UserData::ContentType contentRpmout
"zypp-rpm/transactionsa": Additional rpm output (sent immediately).
#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)