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/io/AsyncDataSource>
64#include <zypp-core/zyppng/io/Process>
65#include <zypp-core/base/IOTools.h>
66#include <zypp-core/zyppng/rpc/rpc.h>
67#include <zypp-core/zyppng/base/private/linuxhelpers_p.h>
68#include <zypp-core/zyppng/base/EventDispatcher>
69#include <zypp-proto/target/commit.pb.h>
70#include <zypp-proto/core/envelope.pb.h>
71#include <zypp-core/zyppng/rpc/zerocopystreams.h>
78#include "tools/zypp-rpm/errorcodes.h"
79#include <rpm/rpmlog.h>
88#include <solv/repo_rpmdb.h>
89#include <solv/chksum.h>
99 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) ->
void {
100 ::solv_chksum_free( chk,
nullptr );
102 if ( ::rpm_hash_database_state( state, chk ) == 0 )
105 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
109 WAR <<
"rpm_hash_database_state failed" << endl;
129 inline void sigMultiversionSpecChanged()
147 for (
const Transaction::Step & step : steps_r )
149 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
159 static const std::string strType(
"type" );
160 static const std::string strStage(
"stage" );
161 static const std::string strSolvable(
"solvable" );
163 static const std::string strTypeDel(
"-" );
164 static const std::string strTypeIns(
"+" );
165 static const std::string strTypeMul(
"M" );
167 static const std::string strStageDone(
"ok" );
168 static const std::string strStageFailed(
"err" );
170 static const std::string strSolvableN(
"n" );
171 static const std::string strSolvableE(
"e" );
172 static const std::string strSolvableV(
"v" );
173 static const std::string strSolvableR(
"r" );
174 static const std::string strSolvableA(
"a" );
181 case Transaction::TRANSACTION_IGNORE:
break;
182 case Transaction::TRANSACTION_ERASE: ret.
add( strType, strTypeDel );
break;
183 case Transaction::TRANSACTION_INSTALL: ret.
add( strType, strTypeIns );
break;
184 case Transaction::TRANSACTION_MULTIINSTALL: ret.
add( strType, strTypeMul );
break;
189 case Transaction::STEP_TODO:
break;
190 case Transaction::STEP_DONE: ret.
add( strStage, strStageDone );
break;
191 case Transaction::STEP_ERROR: ret.
add( strStage, strStageFailed );
break;
200 ident = solv.ident();
207 ident = step_r.
ident();
209 arch = step_r.
arch();
214 { strSolvableV, ed.
version() },
215 { strSolvableR, ed.
release() },
219 s.add( strSolvableE, epoch );
221 ret.
add( strSolvable, s );
235 class AssertMountedBase
247 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
248 execute({
"umount",
"-R",
"-l",
_mountpoint.asString() });
256 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
268 class AssertProcMounted :
private AssertMountedBase
271 AssertProcMounted( Pathname root_r )
274 if ( ! PathInfo(root_r/
"self").isDir() ) {
275 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
277 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
281 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
289 class AssertDevMounted :
private AssertMountedBase
292 AssertDevMounted( Pathname root_r )
295 if ( ! PathInfo(root_r/
"null").isChr() ) {
296 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
301 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
305 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
322 std::ifstream infile( historyFile_r.c_str() );
323 for( iostr::EachLine in( infile ); in; in.next() )
325 const char * ch( (*in).c_str() );
327 if ( *ch <
'1' ||
'9' < *ch )
329 const char * sep1 = ::strchr( ch,
'|' );
334 bool installs =
true;
335 if ( ::strncmp( sep1,
"install|", 8 ) )
337 if ( ::strncmp( sep1,
"remove |", 8 ) )
344 const char * sep2 = ::strchr( sep1,
'|' );
345 if ( !sep2 || sep1 == sep2 )
347 (*in)[sep2-ch] =
'\0';
348 IdString pkg( sep1 );
352 onSystemByUserList.erase( pkg );
356 if ( (sep1 = ::strchr( sep2+1,
'|' ))
357 && (sep1 = ::strchr( sep1+1,
'|' ))
358 && (sep2 = ::strchr( sep1+1,
'|' )) )
360 (*in)[sep2-ch] =
'\0';
361 if ( ::strchr( sep1+1,
'@' ) )
364 onSystemByUserList.insert( pkg );
369 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
370 return onSystemByUserList;
380 return PluginFrame( command_r, json::Object {
381 {
"TransactionStepList", steps_r }
391 MIL <<
"Testcases to keep: " << toKeep << endl;
397 WAR <<
"No Target no Testcase!" << endl;
401 std::string stem(
"updateTestcase" );
402 Pathname dir( target->assertRootPrefix(
"/var/log/") );
406 std::list<std::string> content;
408 std::set<std::string> cases;
409 for_( c, content.begin(), content.end() )
414 if ( cases.size() >= toKeep )
416 unsigned toDel = cases.size() - toKeep + 1;
417 for_( c, cases.begin(), cases.end() )
426 MIL <<
"Write new testcase " << next << endl;
427 getZYpp()->resolver()->createSolverTestcase( next.
asString(),
false );
444 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
454 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
459 WAR <<
"User request to abort script " << script_r << endl;
468 if ( prog.close() != 0 )
470 ret.second = report_r->problem( prog.execError() );
471 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
472 std::ostringstream sstr;
473 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
474 historylog.
comment(sstr.str(),
true);
486 bool executeScript(
const Pathname & root_r,
487 const Pathname & script_r,
488 callback::SendReport<PatchScriptReport> & report_r )
493 action = doExecuteScript( root_r, script_r, report_r );
497 switch ( action.second )
500 WAR <<
"User request to abort at script " << script_r << endl;
505 WAR <<
"User request to skip script " << script_r << endl;
515 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
524 bool RunUpdateScripts(
const Pathname & root_r,
525 const Pathname & scriptsPath_r,
526 const std::vector<sat::Solvable> & checkPackages_r,
529 if ( checkPackages_r.empty() )
532 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
534 if ( ! PathInfo( scriptsDir ).isDir() )
537 std::list<std::string> scripts;
539 if ( scripts.empty() )
547 std::map<std::string, Pathname> unify;
548 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
550 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
551 for_( sit, scripts.begin(), scripts.end() )
556 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
559 PathInfo script( scriptsDir / *sit );
560 Pathname localPath( scriptsPath_r/(*sit) );
561 std::string unifytag;
563 if ( script.isFile() )
569 else if ( ! script.isExist() )
577 if ( unifytag.empty() )
581 if ( unify[unifytag].empty() )
583 unify[unifytag] = localPath;
590 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
591 MIL <<
"Skip update script: " << msg << endl;
592 HistoryLog().comment( msg,
true );
596 if ( abort || aborting_r )
598 WAR <<
"Aborting: Skip update script " << *sit << endl;
599 HistoryLog().comment(
600 localPath.asString() +
_(
" execution skipped while aborting"),
605 MIL <<
"Found update script " << *sit << endl;
606 callback::SendReport<PatchScriptReport> report;
607 report->start( make<Package>( *it ), script.path() );
609 if ( ! executeScript( root_r, localPath, report ) )
621 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
623 std::ifstream infile( file_r.c_str() );
624 for( iostr::EachLine in( infile ); in; in.next() )
626 out_r << *in << endl;
630 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
632 std::string ret( cmd_r );
633#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
634 SUBST_IF(
"%p", notification_r.solvable().asString() );
635 SUBST_IF(
"%P", notification_r.file().asString() );
640 void sendNotification(
const Pathname & root_r,
643 if ( notifications_r.empty() )
647 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
648 if ( cmdspec.empty() )
652 if ( pos == std::string::npos )
654 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
655 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
660 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
662 enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
663 Format format = UNKNOWN;
664 if ( formatStr ==
"none" )
666 else if ( formatStr ==
"single" )
668 else if ( formatStr ==
"digest" )
670 else if ( formatStr ==
"bulk" )
674 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
675 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
683 if ( format == NONE || format == SINGLE )
685 for_( it, notifications_r.begin(), notifications_r.end() )
687 std::vector<std::string> command;
688 if ( format == SINGLE )
690 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
695 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
699 int ret = prog.close();
702 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
703 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
709 else if ( format == DIGEST || format == BULK )
711 filesystem::TmpFile tmpfile;
712 std::ofstream out( tmpfile.path().c_str() );
713 for_( it, notifications_r.begin(), notifications_r.end() )
715 if ( format == DIGEST )
717 out << it->file() << endl;
719 else if ( format == BULK )
725 std::vector<std::string> command;
726 command.push_back(
"<"+tmpfile.path().asString() );
727 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
732 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
736 int ret = prog.close();
739 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
740 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
747 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
748 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
759 void RunUpdateMessages(
const Pathname & root_r,
760 const Pathname & messagesPath_r,
761 const std::vector<sat::Solvable> & checkPackages_r,
762 ZYppCommitResult & result_r )
764 if ( checkPackages_r.empty() )
767 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
769 if ( ! PathInfo( messagesDir ).isDir() )
772 std::list<std::string> messages;
774 if ( messages.empty() )
780 HistoryLog historylog;
781 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
783 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
784 for_( sit, messages.begin(), messages.end() )
789 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
792 PathInfo message( messagesDir / *sit );
793 if ( ! message.isFile() || message.size() == 0 )
796 MIL <<
"Found update message " << *sit << endl;
797 Pathname localPath( messagesPath_r/(*sit) );
798 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
799 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
802 sendNotification( root_r, result_r.updateMessages() );
808 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
811 if ( changedPseudoInstalled.empty() )
819 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
825 HistoryLog historylog;
826 for (
const auto & el : changedPseudoInstalled )
827 historylog.patchStateChange( el.first, el.second );
836 const std::vector<sat::Solvable> & checkPackages_r,
838 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
851 , _requestedLocalesFile( home() /
"RequestedLocales" )
852 , _autoInstalledFile( home() /
"AutoInstalled" )
861 sigMultiversionSpecChanged();
862 MIL <<
"Initialized target on " <<
_root << endl;
870 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
880 boost::function<
bool ()> condition,
881 boost::function<std::string ()> value )
883 std::string val = value();
891 MIL <<
"updating '" << filename <<
"' content." << endl;
895 std::ofstream filestr;
898 filestr.open( filename.
c_str() );
900 if ( filestr.good() )
936 WAR <<
"Can't create anonymous id file" << endl;
945 Pathname flavorpath(
home() /
"LastDistributionFlavor");
951 WAR <<
"No base product, I won't create flavor cache" << endl;
955 std::string flavor = p->flavor();
967 WAR <<
"Can't create flavor cache" << endl;
980 sigMultiversionSpecChanged();
981 MIL <<
"Targets closed" << endl;
1005 Pathname rpmsolvcookie = base/
"cookie";
1007 bool build_rpm_solv =
true;
1017 MIL <<
"Read cookie: " << cookie << endl;
1022 if ( status == rpmstatus )
1023 build_rpm_solv =
false;
1024 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
1025 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
1029 if ( build_rpm_solv )
1043 bool switchingToTmpSolvfile =
false;
1044 Exception ex(
"Failed to cache rpm database.");
1050 rpmsolv = base/
"solv";
1051 rpmsolvcookie = base/
"cookie";
1058 WAR <<
"Using a temporary solv file at " << base << endl;
1059 switchingToTmpSolvfile =
true;
1068 if ( ! switchingToTmpSolvfile )
1078 cmd.push_back(
"rpmdb2solv" );
1080 cmd.push_back(
"-r" );
1083 cmd.push_back(
"-D" );
1085 cmd.push_back(
"-X" );
1087 cmd.push_back(
"-p" );
1090 if ( ! oldSolvFile.
empty() )
1091 cmd.push_back( oldSolvFile.
asString() );
1093 cmd.push_back(
"-o" );
1097 std::string errdetail;
1100 WAR <<
" " << output;
1101 if ( errdetail.empty() ) {
1105 errdetail += output;
1108 int ret = prog.
close();
1129 if (
root() ==
"/" )
1140 if ( !
PathInfo(base/
"solv.idx").isExist() )
1143 return build_rpm_solv;
1161 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1162 ", force loading: " << (force?
"true":
"false") << endl;
1167 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1174 if ( newCache || force )
1191 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1197 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1222 if (
PathInfo( historyFile ).isExist() )
1229 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1230 onSystemByAuto.insert( ident );
1251 if (
PathInfo( needrebootFile ).isFile() )
1252 needrebootSpec.
parseFrom( needrebootFile );
1255 if (
PathInfo( needrebootDir ).isDir() )
1260 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1262 if ( ! isRpmConfigBackup( str_r ) )
1264 Pathname needrebootFile { needrebootDir / str_r };
1265 if (
PathInfo( needrebootFile ).isFile() )
1266 needrebootSpec.
parseFrom( needrebootFile );
1277 if ( ! hardLocks.empty() )
1286 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1298 bool explicitDryRun = policy_r.
dryRun();
1308 if (
root() ==
"/" )
1322 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1341 steps.push_back( *it );
1348 MIL <<
"Todo: " << result << endl;
1358 if ( commitPlugins )
1359 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1366 if ( ! policy_r.
dryRun() )
1372 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1379 if ( ! policy_r.
dryRun() )
1401 DBG <<
"dryRun: Not storing non-package data." << endl;
1408 if ( ! policy_r.
dryRun() )
1410 for_( it, steps.begin(), steps.end() )
1412 if ( ! it->satSolvable().isKind<
Patch>() )
1420 if ( ! patch ||patch->message().empty() )
1423 MIL <<
"Show message for " << patch << endl;
1425 if ( ! report->show( patch ) )
1427 WAR <<
"commit aborted by the user" << endl;
1434 DBG <<
"dryRun: Not checking patch messages." << endl;
1456 for_( it, steps.begin(), steps.end() )
1458 switch ( it->stepType() )
1477 localfile = packageCache.
get( pi );
1480 catch (
const AbortRequestException & exp )
1484 WAR <<
"commit cache preload aborted by the user" << endl;
1488 catch (
const SkipRequestException & exp )
1493 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1503 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1513 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1517 if ( ! policy_r.
dryRun() )
1524 commit( policy_r, packageCache, result );
1529 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1530 if ( explicitDryRun ) {
1544 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1545 if ( explicitDryRun ) {
1557 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1566 if ( commitPlugins )
1567 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1572 if ( ! policy_r.
dryRun() )
1577 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1588 struct NotifyAttemptToModify
1606 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1611 NotifyAttemptToModify attemptToModify( result_r );
1616 AssertProcMounted assertProcMounted(
_root );
1617 AssertDevMounted assertDevMounted(
_root );
1620 std::vector<sat::Solvable> successfullyInstalledPackages;
1623 for_( step, steps.begin(), steps.end() )
1645 localfile = packageCache_r.
get( citem );
1647 catch (
const AbortRequestException &e )
1649 WAR <<
"commit aborted by the user" << endl;
1654 catch (
const SkipRequestException &e )
1657 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1666 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1675 bool success =
false;
1703 WAR <<
"commit aborted by the user" << endl;
1712 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1728 WAR <<
"dry run failed" << endl;
1735 WAR <<
"commit aborted by the user" << endl;
1740 WAR <<
"Install failed" << endl;
1746 if ( success && !policy_r.
dryRun() )
1749 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1758 bool success =
false;
1771 WAR <<
"commit aborted by the user" << endl;
1787 WAR <<
"commit aborted by the user" << endl;
1793 WAR <<
"removal of " << p <<
" failed";
1796 if ( success && !policy_r.
dryRun() )
1803 else if ( ! policy_r.
dryRun() )
1807 if ( ! citem.
buddy() )
1814 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1820 std::string referenceFilename( p->referenceFilename() );
1821 if ( referenceFilename.empty() )
1823 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1827 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1828 if ( !
rpm().hasFile( referencePath.asString() ) )
1833 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1837 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1864 if ( ! successfullyInstalledPackages.empty() )
1867 successfullyInstalledPackages, abort ) )
1869 WAR <<
"Commit aborted by the user" << endl;
1875 successfullyInstalledPackages,
1882 logPatchStatusChanges( result_r.
transaction(), *
this );
1901 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
1904 data.
set(
"line", std::cref(line_r) );
1905 data.set(
"level", level_r );
1911 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
1912 switch ( rpmlevel_r ) {
1913 case RPMLOG_EMERG: [[fallthrough]];
1914 case RPMLOG_ALERT: [[fallthrough]];
1916 return ReportType::loglevel::crt;
1918 return ReportType::loglevel::err;
1919 case RPMLOG_WARNING:
1920 return ReportType::loglevel::war;
1921 default: [[fallthrough]];
1922 case RPMLOG_NOTICE: [[fallthrough]];
1924 return ReportType::loglevel::msg;
1926 return ReportType::loglevel::dbg;
1934 { (*this)->report( userData_r ); }
1947 namespace zpt = zypp::proto::target;
1953 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1958 NotifyAttemptToModify attemptToModify( result_r );
1964 AssertProcMounted assertProcMounted(
_root );
1965 AssertDevMounted assertDevMounted(
_root );
1980 commit.set_flags( flags );
1988 for (
auto &[
_, value] : data ) {
1990 value.resetDispose();
1997 auto &step = steps[stepId];
2014 locCache.value()[stepId] = packageCache_r.
get( citem );
2016 zpt::TransactionStep tStep;
2017 tStep.set_stepid( stepId );
2018 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
2019 tStep.mutable_install()->set_multiversion( p->multiversionInstall() );
2021 *
commit.mutable_steps()->Add( ) = std::move(tStep);
2023 catch (
const AbortRequestException &e )
2025 WAR <<
"commit aborted by the user" << endl;
2030 catch (
const SkipRequestException &e )
2033 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2042 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2048 zpt::TransactionStep tStep;
2049 tStep.set_stepid( stepId );
2050 tStep.mutable_remove()->set_name( p->name() );
2051 tStep.mutable_remove()->set_version( p->edition().version() );
2052 tStep.mutable_remove()->set_release( p->edition().release() );
2053 tStep.mutable_remove()->set_arch( p->arch().asString() );
2055 *
commit.mutable_steps()->Add() = std::move(tStep);
2066 zpt::TransactionStep tStep;
2067 tStep.set_stepid( stepId );
2068 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
2069 tStep.mutable_install()->set_multiversion(
false );
2070 *
commit.mutable_steps()->Add() = std::move(tStep);
2074 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2081 std::vector<sat::Solvable> successfullyInstalledPackages;
2083 if (
commit.steps_size() ) {
2086 auto loop = zyppng::EventLoop::create();
2095 int currentStepId = -1;
2101 bool gotEndOfScript =
false;
2104 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2105 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2106 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2107 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2108 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2111 std::optional<zpt::TransactionError> transactionError;
2114 std::string currentScriptType;
2115 std::string currentScriptPackage;
2125 unsigned lineno = 0;
2128 auto msgSource = zyppng::AsyncDataSource::create();
2129 auto scriptSource = zyppng::AsyncDataSource::create();
2134 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2136 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2138 if ( currentStepId >= 0 )
2139 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2140 cmdout.
set(
"line", line );
2144 if ( installreport ) {
2146 }
else if ( uninstallreport ) {
2148 }
else if ( scriptreport ) {
2150 }
else if ( transactionreport ) {
2152 }
else if ( cleanupreport ) {
2155 WAR <<
"Got rpm output without active report " << line;
2160 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2164 if ( line.back() !=
'\n' )
2170 const auto &processDataFromScriptFd = [&](){
2172 while ( scriptSource->canReadLine() ) {
2174 if ( gotEndOfScript )
2177 std::string l = scriptSource->readLine().asString();
2179 gotEndOfScript =
true;
2183 l = l.substr( 0, rawsize );
2185 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2186 sendRpmLineToReport( l );
2189 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2192 const auto &waitForScriptEnd = [&]() {
2195 if ( gotEndOfScript )
2199 processDataFromScriptFd();
2202 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2205 scriptSource->waitForReadyRead( 100 );
2209 const auto &aboutToStartNewReport = [&](){
2211 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2212 ERR <<
"There is still a running report, this is a bug" << std::endl;
2216 gotEndOfScript =
false;
2219 const auto &writeRpmMsgToHistory = [&](){
2220 if ( rpmmsg.size() == 0 )
2224 rpmmsg +=
"[truncated]\n";
2226 std::ostringstream sstr;
2227 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2232 const auto &finalizeCurrentReport = [&]() {
2235 if ( currentStepId >= 0 ) {
2236 step = &steps.at(currentStepId);
2240 if ( installreport ) {
2248 writeRpmMsgToHistory();
2252 ( *installreport)->progress( 100, resObj );
2255 if ( currentStepId >= 0 )
2256 locCache.value().erase( currentStepId );
2257 successfullyInstalledPackages.push_back( step->
satSolvable() );
2263 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2275 writeRpmMsgToHistory();
2278 if ( uninstallreport ) {
2286 writeRpmMsgToHistory();
2290 ( *uninstallreport)->progress( 100, resObj );
2300 writeRpmMsgToHistory();
2303 if ( scriptreport ) {
2305 ( *scriptreport)->progress( 100, resObj );
2308 if ( transactionreport ) {
2310 ( *transactionreport)->progress( 100 );
2313 if ( cleanupreport ) {
2315 ( *cleanupreport)->progress( 100 );
2321 currentScriptType.clear();
2322 currentScriptPackage.clear();
2323 installreport.reset();
2324 uninstallreport.reset();
2325 scriptreport.reset();
2326 transactionreport.reset();
2327 cleanupreport.reset();
2337 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2339 const char *argv[] = {
2342 zyppRpmBinary.data(),
2345 auto prog = zyppng::Process::create();
2349 auto messagePipe = zyppng::Pipe::create();
2355 auto scriptPipe = zyppng::Pipe::create();
2359 prog->addFd( messagePipe->writeFd );
2360 prog->addFd( scriptPipe->writeFd );
2363 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2366 prog->sigStarted().connect( [&](){
2369 messagePipe->unrefWrite();
2370 scriptPipe->unrefWrite();
2373 prog->connectFunc( &zyppng::IODevice::sigChannelReadyRead, [&](
int channel ){
2374 while( prog->canReadLine( channel ) ) {
2375 L_ERR(
"zypp-rpm") << ( channel == zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2381 const auto outFd = prog->stdinFd();
2388 zyppng::rpc::HeaderSizeType msgSize =
commit.ByteSizeLong();
2389 const auto written = zyppng::eintrSafeCall(
::write, outFd, &msgSize,
sizeof(zyppng::rpc::HeaderSizeType) );
2390 if ( written !=
sizeof(zyppng::rpc::HeaderSizeType) ) {
2391 prog->stop( SIGKILL );
2395 zyppng::FileOutputStream fo ( outFd );
2396 if ( !
commit.SerializeToZeroCopyStream( &fo ) ) {
2397 prog->stop( SIGKILL );
2407 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd } ) )
2410 zyppng::rpc::HeaderSizeType pendingMessageSize = 0;
2411 const auto &processMessages = [&] ( ) {
2415 const auto &parseMsgWithStepId = [&steps](
const auto &m,
auto &p ){
2416 if ( !p.ParseFromString( m.value() ) ) {
2417 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2421 auto id = p.stepid();
2422 if ( id < 0 || id >= steps.size() ) {
2423 ERR <<
"Received invalid stepId: " <<
id <<
" in " << m.messagetypename() <<
" message from zypp-rpm, ignoring." << std::endl;
2429 while ( msgSource->bytesAvailable() ) {
2431 if ( pendingMessageSize == 0 ) {
2432 if ( std::size_t(msgSource->bytesAvailable()) >=
sizeof( zyppng::rpc::HeaderSizeType ) ) {
2433 msgSource->read(
reinterpret_cast<char *
>( &pendingMessageSize ),
sizeof( zyppng::rpc::HeaderSizeType ) );
2437 if ( msgSource->bytesAvailable() < pendingMessageSize ) {
2441 auto bytes = msgSource->read( pendingMessageSize );
2442 pendingMessageSize = 0;
2444 zypp::proto::Envelope m;
2445 if (! m.ParseFromArray( bytes.data(), bytes.size() ) ) {
2448 ERR <<
"Received misformed message from zypp-rpm, ignoring" << std::endl;
2456 const auto &mName = m.messagetypename();
2457 if ( mName ==
"zypp.proto.target.RpmLog" ) {
2460 if ( !p.ParseFromString( m.value() ) ) {
2461 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2464 ( p.level() >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2465 : p.level() >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2466 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p.level() <<
"> " << p.line();
2469 }
else if ( mName ==
"zypp.proto.target.PackageBegin" ) {
2470 finalizeCurrentReport();
2472 zpt::PackageBegin p;
2473 if ( !parseMsgWithStepId( m, p ) )
2476 aboutToStartNewReport();
2478 auto & step = steps.at( p.stepid() );
2479 currentStepId = p.stepid();
2481 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2482 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2484 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2485 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2488 }
else if ( mName ==
"zypp.proto.target.PackageFinished" ) {
2489 zpt::PackageFinished p;
2490 if ( !parseMsgWithStepId( m, p ) )
2493 if ( p.stepid() < 0 || p.stepid() > steps.size() )
2500 }
else if ( mName ==
"zypp.proto.target.PackageProgress" ) {
2501 zpt::PackageProgress p;
2502 if ( !parseMsgWithStepId( m, p ) )
2505 if ( uninstallreport )
2506 (*uninstallreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2507 else if ( installreport )
2508 (*installreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2510 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2512 }
else if ( mName ==
"zypp.proto.target.PackageError" ) {
2513 zpt::PackageError p;
2514 if ( !parseMsgWithStepId( m, p ) )
2517 if ( p.stepid() >= 0 && p.stepid() < steps.size() )
2520 finalizeCurrentReport();
2522 }
else if ( mName ==
"zypp.proto.target.ScriptBegin" ) {
2523 finalizeCurrentReport();
2526 if ( !p.ParseFromString( m.value() ) ) {
2527 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2531 aboutToStartNewReport();
2534 const auto stepId = p.stepid();
2535 if ( stepId >= 0 && stepId < steps.size() ) {
2539 currentStepId = p.stepid();
2540 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2541 currentScriptType = p.scripttype();
2542 currentScriptPackage = p.scriptpackage();
2543 (*scriptreport)->start( p.scripttype(), p.scriptpackage(), resPtr );
2545 }
else if ( mName ==
"zypp.proto.target.ScriptFinished" ) {
2549 }
else if ( mName ==
"zypp.proto.target.ScriptError" ) {
2552 if ( !p.ParseFromString( m.value() ) ) {
2553 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2558 const auto stepId = p.stepid();
2559 if ( stepId >= 0 && stepId < steps.size() ) {
2569 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2572 writeRpmMsgToHistory();
2574 if ( !scriptreport ) {
2575 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2584 scriptreport.reset();
2587 }
else if ( mName ==
"zypp.proto.target.CleanupBegin" ) {
2588 finalizeCurrentReport();
2590 zpt::CleanupBegin beg;
2591 if ( !beg.ParseFromString( m.value() ) ) {
2592 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2596 aboutToStartNewReport();
2597 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2598 (*cleanupreport)->start( beg.nvra() );
2599 }
else if ( mName ==
"zypp.proto.target.CleanupFinished" ) {
2601 finalizeCurrentReport();
2603 }
else if ( mName ==
"zypp.proto.target.CleanupProgress" ) {
2604 zpt::CleanupProgress prog;
2605 if ( !prog.ParseFromString( m.value() ) ) {
2606 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2610 if ( !cleanupreport ) {
2611 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2615 (*cleanupreport)->progress( prog.amount() );
2617 }
else if ( mName ==
"zypp.proto.target.TransBegin" ) {
2618 finalizeCurrentReport();
2620 zpt::TransBegin beg;
2621 if ( !beg.ParseFromString( m.value() ) ) {
2622 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2626 aboutToStartNewReport();
2627 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2628 (*transactionreport)->start( beg.name() );
2629 }
else if ( mName ==
"zypp.proto.target.TransFinished" ) {
2631 finalizeCurrentReport();
2633 }
else if ( mName ==
"zypp.proto.target.TransProgress" ) {
2634 zpt::TransProgress prog;
2635 if ( !prog.ParseFromString( m.value() ) ) {
2636 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2640 if ( !transactionreport ) {
2641 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2645 (*transactionreport)->progress( prog.amount() );
2646 }
else if ( mName ==
"zypp.proto.target.TransactionError" ) {
2648 zpt::TransactionError error;
2649 if ( !error.ParseFromString( m.value() ) ) {
2650 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2655 transactionError = std::move(error);
2658 ERR <<
"Received unexpected message from zypp-rpm: "<< m.messagetypename() <<
", ignoring" << std::endl;
2664 msgSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, processMessages );
2667 int zyppRpmExitCode = -1;
2668 prog->connectFunc( &zyppng::Process::sigFinished, [&](
int code ){
2669 zyppRpmExitCode = code;
2673 if ( !prog->start( argv ) ) {
2684 finalizeCurrentReport();
2687 bool readMsgs =
false;
2688 while( prog->canReadLine( zyppng::Process::StdErr ) ) {
2690 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdErr ).asStringView();
2692 while( prog->canReadLine( zyppng::Process::StdOut ) ) {
2694 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdOut ).asStringView();
2697 while ( scriptSource->canReadLine() ) {
2699 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2701 if ( scriptSource->bytesAvailable() > 0 ) {
2703 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2708 switch ( zyppRpmExitCode ) {
2710 case zypprpm::NoError:
2711 case zypprpm::RpmFinishedWithError:
2713 case zypprpm::RpmFinishedWithTransactionError: {
2715 if ( transactionError ) {
2717 std::ostringstream sstr;
2718 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2719 for (
const auto & err : transactionError->problems() ) {
2720 sstr <<
" " << err.message() <<
"\n";
2730 case zypprpm::FailedToOpenDb:
2733 case zypprpm::WrongHeaderSize:
2734 case zypprpm::WrongMessageFormat:
2737 case zypprpm::RpmInitFailed:
2740 case zypprpm::FailedToReadPackage:
2743 case zypprpm::FailedToAddStepToTransaction:
2746 case zypprpm::RpmOrderFailed:
2752 auto &step = steps[stepId];
2764 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2768 std::string referenceFilename( p->referenceFilename() );
2770 if ( referenceFilename.empty() ) {
2771 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2773 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2775 if ( !
rpm().hasFile( referencePath.asString() ) ) {
2779 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2781 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2795 if ( ! successfullyInstalledPackages.empty() )
2798 successfullyInstalledPackages, abort ) )
2800 WAR <<
"Commit aborted by the user" << endl;
2806 successfullyInstalledPackages,
2813 logPatchStatusChanges( result_r.
transaction(), *
this );
2841 if ( baseproduct.isFile() )
2854 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2859 inline Pathname staticGuessRoot(
const Pathname & root_r )
2861 if ( root_r.empty() )
2866 return Pathname(
"/");
2872 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2874 std::ifstream idfile( file_r.c_str() );
2875 for( iostr::EachLine in( idfile ); in; in.next() )
2878 if ( ! line.empty() )
2881 return std::string();
2892 if ( p->isTargetDistribution() )
2900 const Pathname needroot( staticGuessRoot(root_r) );
2901 const Target_constPtr target( getZYpp()->getTarget() );
2902 if ( target && target->root() == needroot )
2903 return target->requestedLocales();
2909 MIL <<
"updateAutoInstalled if changed..." << endl;
2917 {
return baseproductdata(
_root ).registerTarget(); }
2920 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
2923 {
return baseproductdata(
_root ).registerRelease(); }
2926 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
2929 {
return baseproductdata(
_root ).registerFlavor(); }
2932 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
2965 std::string
distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version();
2972 scoped_ptr<rpm::RpmDb> tmprpmdb;
2978 tmprpmdb->initDatabase( );
2995 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3000 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3006 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3009 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3010 if ( ret.
empty() && root_r !=
"/" )
3013 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3021 return guessAnonymousUniqueId(
root() );
3026 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3033 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...
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.
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.
bool collectScriptFromPackage(ManagedFile rpmPackage_r)
Extract and remember a packages posttrans script for later execution.
bool executeScripts()
Execute the remembered scripts.
void discardScripts()
Discard all remembered scrips.
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.
bool write(const Pathname &path_r, const std::string &key_r, const std::string &val_r, const std::string &newcomment_r)
Add or change a value in sysconfig file path_r.
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)
IMPL_PTR_TYPE(TargetImpl)
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
std::string rpmDbStateHash(const Pathname &root_r)
void writeUpgradeTestcase()
static bool fileMissing(const Pathname &pathname)
helper functor
void updateFileContent(const Pathname &filename, boost::function< bool()> condition, boost::function< std::string()> value)
updates the content of filename if condition is true, setting the content the the value returned by v...
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
static std::string generateRandomId()
generates a random id using uuidgen
Easy-to use interface to the ZYPP dependency resolver.
std::unordered_set< Locale > LocaleSet
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
std::list< UpdateNotificationFile > UpdateNotifications
std::string asString(const Patch::Category &obj)
@ 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.
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.