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>
87 static bool val = [](){
88 const char * env = getenv(
"TRANSACTIONAL_UPDATE");
100#include <solv/repo_rpmdb.h>
101#include <solv/chksum.h>
111 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) ->
void {
112 ::solv_chksum_free( chk,
nullptr );
114 if ( ::rpm_hash_database_state( state, chk ) == 0 )
117 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
121 WAR <<
"rpm_hash_database_state failed" << endl;
141 inline void sigMultiversionSpecChanged()
159 for (
const Transaction::Step & step : steps_r )
161 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
171 static const std::string strType(
"type" );
172 static const std::string strStage(
"stage" );
173 static const std::string strSolvable(
"solvable" );
175 static const std::string strTypeDel(
"-" );
176 static const std::string strTypeIns(
"+" );
177 static const std::string strTypeMul(
"M" );
179 static const std::string strStageDone(
"ok" );
180 static const std::string strStageFailed(
"err" );
182 static const std::string strSolvableN(
"n" );
183 static const std::string strSolvableE(
"e" );
184 static const std::string strSolvableV(
"v" );
185 static const std::string strSolvableR(
"r" );
186 static const std::string strSolvableA(
"a" );
193 case Transaction::TRANSACTION_IGNORE:
break;
194 case Transaction::TRANSACTION_ERASE: ret.
add( strType, strTypeDel );
break;
195 case Transaction::TRANSACTION_INSTALL: ret.
add( strType, strTypeIns );
break;
196 case Transaction::TRANSACTION_MULTIINSTALL: ret.
add( strType, strTypeMul );
break;
201 case Transaction::STEP_TODO:
break;
202 case Transaction::STEP_DONE: ret.
add( strStage, strStageDone );
break;
203 case Transaction::STEP_ERROR: ret.
add( strStage, strStageFailed );
break;
212 ident = solv.ident();
219 ident = step_r.
ident();
221 arch = step_r.
arch();
226 { strSolvableV, ed.
version() },
227 { strSolvableR, ed.
release() },
231 s.add( strSolvableE, epoch );
233 ret.
add( strSolvable, s );
247 class AssertMountedBase
259 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
260 execute({
"umount",
"-R",
"-l",
_mountpoint.asString() });
268 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
280 class AssertProcMounted :
private AssertMountedBase
283 AssertProcMounted( Pathname root_r )
286 if ( ! PathInfo(root_r/
"self").isDir() ) {
287 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
289 && execute({
"mount",
"-t",
"proc",
"/proc", root_r.asString() }) == 0 ) {
293 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
301 class AssertDevMounted :
private AssertMountedBase
304 AssertDevMounted( Pathname root_r )
307 if ( ! PathInfo(root_r/
"null").isChr() ) {
308 MIL <<
"Try to make sure dev is mounted at" << root_r << endl;
313 && execute({
"mount",
"--rbind",
"--make-rslave",
"/dev", root_r.asString() }) == 0 ) {
317 WAR <<
"Mounting dev at " << root_r <<
" failed" << endl;
334 std::ifstream infile( historyFile_r.c_str() );
335 for( iostr::EachLine in( infile ); in; in.next() )
337 const char * ch( (*in).c_str() );
339 if ( *ch <
'1' ||
'9' < *ch )
341 const char * sep1 = ::strchr( ch,
'|' );
346 bool installs =
true;
347 if ( ::strncmp( sep1,
"install|", 8 ) )
349 if ( ::strncmp( sep1,
"remove |", 8 ) )
356 const char * sep2 = ::strchr( sep1,
'|' );
357 if ( !sep2 || sep1 == sep2 )
359 (*in)[sep2-ch] =
'\0';
360 IdString pkg( sep1 );
364 onSystemByUserList.erase( pkg );
368 if ( (sep1 = ::strchr( sep2+1,
'|' ))
369 && (sep1 = ::strchr( sep1+1,
'|' ))
370 && (sep2 = ::strchr( sep1+1,
'|' )) )
372 (*in)[sep2-ch] =
'\0';
373 if ( ::strchr( sep1+1,
'@' ) )
376 onSystemByUserList.insert( pkg );
381 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
382 return onSystemByUserList;
392 return PluginFrame( command_r, json::Object {
393 {
"TransactionStepList", steps_r }
403 MIL <<
"Testcases to keep: " << toKeep << endl;
409 WAR <<
"No Target no Testcase!" << endl;
413 std::string stem(
"updateTestcase" );
414 Pathname dir( target->assertRootPrefix(
"/var/log/") );
418 std::list<std::string> content;
420 std::set<std::string> cases;
421 for_( c, content.begin(), content.end() )
426 if ( cases.size() >= toKeep )
428 unsigned toDel = cases.size() - toKeep + 1;
429 for_( c, cases.begin(), cases.end() )
438 MIL <<
"Write new testcase " << next << endl;
439 getZYpp()->resolver()->createSolverTestcase( next.
asString(),
false );
456 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
466 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
471 WAR <<
"User request to abort script " << script_r << endl;
480 if ( prog.close() != 0 )
482 ret.second = report_r->problem( prog.execError() );
483 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
484 std::ostringstream sstr;
485 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
486 historylog.
comment(sstr.str(),
true);
498 bool executeScript(
const Pathname & root_r,
499 const Pathname & script_r,
500 callback::SendReport<PatchScriptReport> & report_r )
505 action = doExecuteScript( root_r, script_r, report_r );
509 switch ( action.second )
512 WAR <<
"User request to abort at script " << script_r << endl;
517 WAR <<
"User request to skip script " << script_r << endl;
527 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
536 bool RunUpdateScripts(
const Pathname & root_r,
537 const Pathname & scriptsPath_r,
538 const std::vector<sat::Solvable> & checkPackages_r,
541 if ( checkPackages_r.empty() )
544 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
546 if ( ! PathInfo( scriptsDir ).isDir() )
549 std::list<std::string> scripts;
551 if ( scripts.empty() )
559 std::map<std::string, Pathname> unify;
560 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
562 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
563 for_( sit, scripts.begin(), scripts.end() )
568 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
571 PathInfo script( scriptsDir / *sit );
572 Pathname localPath( scriptsPath_r/(*sit) );
573 std::string unifytag;
575 if ( script.isFile() )
581 else if ( ! script.isExist() )
589 if ( unifytag.empty() )
593 if ( unify[unifytag].empty() )
595 unify[unifytag] = localPath;
602 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
603 MIL <<
"Skip update script: " << msg << endl;
604 HistoryLog().comment( msg,
true );
608 if ( abort || aborting_r )
610 WAR <<
"Aborting: Skip update script " << *sit << endl;
611 HistoryLog().comment(
612 localPath.asString() +
_(
" execution skipped while aborting"),
617 MIL <<
"Found update script " << *sit << endl;
618 callback::SendReport<PatchScriptReport> report;
619 report->start( make<Package>( *it ), script.path() );
621 if ( ! executeScript( root_r, localPath, report ) )
633 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
635 std::ifstream infile( file_r.c_str() );
636 for( iostr::EachLine in( infile ); in; in.next() )
638 out_r << *in << endl;
642 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
644 std::string ret( cmd_r );
645#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
646 SUBST_IF(
"%p", notification_r.solvable().asString() );
647 SUBST_IF(
"%P", notification_r.file().asString() );
652 void sendNotification(
const Pathname & root_r,
655 if ( notifications_r.empty() )
659 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
660 if ( cmdspec.empty() )
663 std::string::size_type pos( cmdspec.find(
'|' ) );
664 if ( pos == std::string::npos )
666 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
667 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
672 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
674 enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
675 Format format = UNKNOWN;
676 if ( formatStr ==
"none" )
678 else if ( formatStr ==
"single" )
680 else if ( formatStr ==
"digest" )
682 else if ( formatStr ==
"bulk" )
686 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
687 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
695 if ( format == NONE || format == SINGLE )
697 for_( it, notifications_r.begin(), notifications_r.end() )
699 std::vector<std::string> command;
700 if ( format == SINGLE )
702 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
707 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
711 int ret = prog.close();
714 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
715 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
721 else if ( format == DIGEST || format == BULK )
723 filesystem::TmpFile tmpfile;
724 std::ofstream out( tmpfile.path().c_str() );
725 for_( it, notifications_r.begin(), notifications_r.end() )
727 if ( format == DIGEST )
729 out << it->file() << endl;
731 else if ( format == BULK )
737 std::vector<std::string> command;
738 command.push_back(
"<"+tmpfile.path().asString() );
739 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
744 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
748 int ret = prog.close();
751 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
752 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
759 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
760 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
771 void RunUpdateMessages(
const Pathname & root_r,
772 const Pathname & messagesPath_r,
773 const std::vector<sat::Solvable> & checkPackages_r,
774 ZYppCommitResult & result_r )
776 if ( checkPackages_r.empty() )
779 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
781 if ( ! PathInfo( messagesDir ).isDir() )
784 std::list<std::string> messages;
786 if ( messages.empty() )
792 HistoryLog historylog;
793 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
795 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
796 for_( sit, messages.begin(), messages.end() )
801 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
804 PathInfo message( messagesDir / *sit );
805 if ( ! message.isFile() || message.size() == 0 )
808 MIL <<
"Found update message " << *sit << endl;
809 Pathname localPath( messagesPath_r/(*sit) );
810 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
811 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
814 sendNotification( root_r, result_r.updateMessages() );
820 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
823 if ( changedPseudoInstalled.empty() )
831 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
837 HistoryLog historylog;
838 for (
const auto & el : changedPseudoInstalled )
839 historylog.patchStateChange( el.first, el.second );
848 const std::vector<sat::Solvable> & checkPackages_r,
850 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
863 , _requestedLocalesFile( home() /
"RequestedLocales" )
864 , _autoInstalledFile( home() /
"AutoInstalled" )
873 sigMultiversionSpecChanged();
874 MIL <<
"Initialized target on " <<
_root << endl;
882 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
892 boost::function<
bool ()> condition,
893 boost::function<std::string ()> value )
895 std::string val = value();
903 MIL <<
"updating '" << filename <<
"' content." << endl;
907 std::ofstream filestr;
910 filestr.open( filename.
c_str() );
912 if ( filestr.good() )
948 WAR <<
"Can't create anonymous id file" << endl;
957 Pathname flavorpath(
home() /
"LastDistributionFlavor");
963 WAR <<
"No base product, I won't create flavor cache" << endl;
967 std::string flavor = p->flavor();
979 WAR <<
"Can't create flavor cache" << endl;
992 sigMultiversionSpecChanged();
993 MIL <<
"Closed target on " <<
_root << endl;
1017 Pathname rpmsolvcookie = base/
"cookie";
1019 bool build_rpm_solv =
true;
1029 MIL <<
"Read cookie: " << cookie << endl;
1034 if ( status == rpmstatus )
1035 build_rpm_solv =
false;
1036 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
1037 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
1041 if ( build_rpm_solv )
1055 bool switchingToTmpSolvfile =
false;
1056 Exception ex(
"Failed to cache rpm database.");
1062 rpmsolv = base/
"solv";
1063 rpmsolvcookie = base/
"cookie";
1070 WAR <<
"Using a temporary solv file at " << base << endl;
1071 switchingToTmpSolvfile =
true;
1080 if ( ! switchingToTmpSolvfile )
1090 cmd.push_back(
"rpmdb2solv" );
1092 cmd.push_back(
"-r" );
1095 cmd.push_back(
"-D" );
1096 cmd.push_back(
rpm().dbPath().asString() );
1097 cmd.push_back(
"-X" );
1099 cmd.push_back(
"-p" );
1102 if ( ! oldSolvFile.
empty() )
1103 cmd.push_back( oldSolvFile.
asString() );
1105 cmd.push_back(
"-o" );
1109 std::string errdetail;
1112 WAR <<
" " << output;
1113 if ( errdetail.empty() ) {
1117 errdetail += output;
1120 int ret = prog.
close();
1141 if (
root() ==
"/" )
1152 if ( !
PathInfo(base/
"solv.idx").isExist() )
1155 return build_rpm_solv;
1173 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1174 ", force loading: " << (force?
"true":
"false") << endl;
1179 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1186 if ( newCache || force )
1203 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1209 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1234 if (
PathInfo( historyFile ).isExist() )
1241 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1242 onSystemByAuto.insert( ident );
1263 if (
PathInfo( needrebootFile ).isFile() )
1264 needrebootSpec.
parseFrom( needrebootFile );
1267 if (
PathInfo( needrebootDir ).isDir() )
1272 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1274 if ( ! isRpmConfigBackup( str_r ) )
1276 Pathname needrebootFile { needrebootDir / str_r };
1277 if (
PathInfo( needrebootFile ).isFile() )
1278 needrebootSpec.
parseFrom( needrebootFile );
1289 if ( ! hardLocks.empty() )
1298 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1310 bool explicitDryRun = policy_r.
dryRun();
1320 if (
root() ==
"/" )
1334 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1353 steps.push_back( *it );
1360 MIL <<
"Todo: " << result << endl;
1371 if ( commitPlugins )
1372 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1379 if ( ! policy_r.
dryRun() )
1385 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1392 if ( ! policy_r.
dryRun() )
1414 DBG <<
"dryRun: Not storing non-package data." << endl;
1421 if ( ! policy_r.
dryRun() )
1423 for_( it, steps.begin(), steps.end() )
1425 if ( ! it->satSolvable().isKind<
Patch>() )
1433 if ( ! patch ||patch->message().empty() )
1436 MIL <<
"Show message for " << patch << endl;
1438 if ( ! report->show( patch ) )
1440 WAR <<
"commit aborted by the user" << endl;
1447 DBG <<
"dryRun: Not checking patch messages." << endl;
1469 for_( it, steps.begin(), steps.end() )
1471 switch ( it->stepType() )
1490 localfile = packageCache.
get( pi );
1493 catch (
const AbortRequestException & exp )
1497 WAR <<
"commit cache preload aborted by the user" << endl;
1501 catch (
const SkipRequestException & exp )
1506 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1516 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1526 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1530 if ( ! policy_r.
dryRun() )
1537 commit( policy_r, packageCache, result );
1542 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1543 if ( explicitDryRun ) {
1557 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1558 if ( explicitDryRun ) {
1570 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1579 if ( commitPlugins )
1580 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1585 if ( ! policy_r.
dryRun() )
1590 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1601 struct NotifyAttemptToModify
1606 {
if ( _guard ) {
_result.attemptToModify(
true );
_guard =
false; } }
1619 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1624 NotifyAttemptToModify attemptToModify( result_r );
1629 AssertProcMounted assertProcMounted(
_root );
1630 AssertDevMounted assertDevMounted(
_root );
1633 std::vector<sat::Solvable> successfullyInstalledPackages;
1636 for_( step, steps.begin(), steps.end() )
1658 localfile = packageCache_r.
get( citem );
1660 catch (
const AbortRequestException &e )
1662 WAR <<
"commit aborted by the user" << endl;
1667 catch (
const SkipRequestException &e )
1670 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1679 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1688 bool success =
false;
1714 WAR <<
"commit aborted by the user" << endl;
1723 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1739 WAR <<
"dry run failed" << endl;
1746 WAR <<
"commit aborted by the user" << endl;
1751 WAR <<
"Install failed" << endl;
1757 if ( success && !policy_r.
dryRun() )
1760 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1769 bool success =
false;
1782 WAR <<
"commit aborted by the user" << endl;
1798 WAR <<
"commit aborted by the user" << endl;
1804 WAR <<
"removal of " << p <<
" failed";
1807 if ( success && !policy_r.
dryRun() )
1814 else if ( ! policy_r.
dryRun() )
1818 if ( ! citem.
buddy() )
1825 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1831 std::string referenceFilename( p->referenceFilename() );
1832 if ( referenceFilename.empty() )
1834 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1838 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1839 if ( !
rpm().hasFile( referencePath.asString() ) )
1844 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1848 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1877 if ( ! successfullyInstalledPackages.empty() )
1880 successfullyInstalledPackages, abort ) )
1882 WAR <<
"Commit aborted by the user" << endl;
1888 successfullyInstalledPackages,
1895 logPatchStatusChanges( result_r.
transaction(), *
this );
1914 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
1917 data.
set(
"line", std::cref(line_r) );
1918 data.set(
"level", level_r );
1924 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
1925 switch ( rpmlevel_r ) {
1926 case RPMLOG_EMERG: [[fallthrough]];
1927 case RPMLOG_ALERT: [[fallthrough]];
1929 return ReportType::loglevel::crt;
1931 return ReportType::loglevel::err;
1932 case RPMLOG_WARNING:
1933 return ReportType::loglevel::war;
1934 default: [[fallthrough]];
1935 case RPMLOG_NOTICE: [[fallthrough]];
1937 return ReportType::loglevel::msg;
1939 return ReportType::loglevel::dbg;
1947 { (*this)->report( userData_r ); }
1960 namespace zpt = zypp::proto::target;
1966 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1971 NotifyAttemptToModify attemptToModify( result_r );
1977 AssertProcMounted assertProcMounted(
_root );
1978 AssertDevMounted assertDevMounted(
_root );
1993 commit.set_flags( flags );
1996 commit.set_dbpath(
rpm().dbPath().asString() );
2002 for (
auto &[
_, value] : data ) {
2004 value.resetDispose();
2010 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
2011 auto &step = steps[stepId];
2028 locCache.value()[stepId] = packageCache_r.
get( citem );
2030 zpt::TransactionStep tStep;
2031 tStep.set_stepid( stepId );
2032 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
2033 tStep.mutable_install()->set_multiversion( p->multiversionInstall() );
2035 *
commit.mutable_steps()->Add( ) = std::move(tStep);
2037 catch (
const AbortRequestException &e )
2039 WAR <<
"commit aborted by the user" << endl;
2044 catch (
const SkipRequestException &e )
2047 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2056 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2062 zpt::TransactionStep tStep;
2063 tStep.set_stepid( stepId );
2064 tStep.mutable_remove()->set_name( p->name() );
2065 tStep.mutable_remove()->set_version( p->edition().version() );
2066 tStep.mutable_remove()->set_release( p->edition().release() );
2067 tStep.mutable_remove()->set_arch( p->arch().asString() );
2069 *
commit.mutable_steps()->Add() = std::move(tStep);
2080 zpt::TransactionStep tStep;
2081 tStep.set_stepid( stepId );
2082 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
2083 tStep.mutable_install()->set_multiversion(
false );
2084 *
commit.mutable_steps()->Add() = std::move(tStep);
2088 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2095 std::vector<sat::Solvable> successfullyInstalledPackages;
2097 if (
commit.steps_size() ) {
2100 auto loop = zyppng::EventLoop::create();
2104 const std::vector<int> interceptedSignals {
2111 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2112 unixSignals->sigReceived ().connect ([](
int signum ){
2114 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 );
2116 for(
const auto &sig : interceptedSignals )
2117 unixSignals->addSignal ( sig );
2120 for(
const auto &sig : interceptedSignals )
2121 unixSignals->removeSignal ( sig );
2128 int currentStepId = -1;
2134 bool gotEndOfScript =
false;
2137 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2138 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2139 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2140 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2141 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2144 std::optional<zpt::TransactionError> transactionError;
2147 std::string currentScriptType;
2148 std::string currentScriptPackage;
2158 unsigned lineno = 0;
2161 auto msgSource = zyppng::AsyncDataSource::create();
2162 auto scriptSource = zyppng::AsyncDataSource::create();
2167 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2169 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2171 if ( currentStepId >= 0 )
2172 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2173 cmdout.
set(
"line", line );
2177 if ( installreport ) {
2179 }
else if ( uninstallreport ) {
2181 }
else if ( scriptreport ) {
2183 }
else if ( transactionreport ) {
2185 }
else if ( cleanupreport ) {
2188 WAR <<
"Got rpm output without active report " << line;
2193 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2197 if ( line.back() !=
'\n' )
2203 const auto &processDataFromScriptFd = [&](){
2205 while ( scriptSource->canReadLine() ) {
2207 if ( gotEndOfScript )
2210 std::string l = scriptSource->readLine().asString();
2212 gotEndOfScript =
true;
2213 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2216 l = l.substr( 0, rawsize );
2218 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2219 sendRpmLineToReport( l );
2222 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2225 const auto &waitForScriptEnd = [&]() {
2228 if ( gotEndOfScript )
2232 processDataFromScriptFd();
2235 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2238 scriptSource->waitForReadyRead( 100 );
2242 const auto &aboutToStartNewReport = [&](){
2244 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2245 ERR <<
"There is still a running report, this is a bug" << std::endl;
2249 gotEndOfScript =
false;
2252 const auto &writeRpmMsgToHistory = [&](){
2253 if ( rpmmsg.size() == 0 )
2257 rpmmsg +=
"[truncated]\n";
2259 std::ostringstream sstr;
2260 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2265 const auto &finalizeCurrentReport = [&]() {
2268 if ( currentStepId >= 0 ) {
2269 step = &steps.at(currentStepId);
2273 if ( installreport ) {
2281 writeRpmMsgToHistory();
2285 ( *installreport)->progress( 100, resObj );
2288 if ( currentStepId >= 0 )
2289 locCache.value().erase( currentStepId );
2290 successfullyInstalledPackages.push_back( step->
satSolvable() );
2296 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2308 writeRpmMsgToHistory();
2311 if ( uninstallreport ) {
2319 writeRpmMsgToHistory();
2323 ( *uninstallreport)->progress( 100, resObj );
2333 writeRpmMsgToHistory();
2336 if ( scriptreport ) {
2338 ( *scriptreport)->progress( 100, resObj );
2341 if ( transactionreport ) {
2343 ( *transactionreport)->progress( 100 );
2346 if ( cleanupreport ) {
2348 ( *cleanupreport)->progress( 100 );
2354 currentScriptType.clear();
2355 currentScriptPackage.clear();
2356 installreport.reset();
2357 uninstallreport.reset();
2358 scriptreport.reset();
2359 transactionreport.reset();
2360 cleanupreport.reset();
2370 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2372 const char *argv[] = {
2375 zyppRpmBinary.data(),
2378 auto prog = zyppng::Process::create();
2382 auto messagePipe = zyppng::Pipe::create();
2388 auto scriptPipe = zyppng::Pipe::create();
2392 prog->addFd( messagePipe->writeFd );
2393 prog->addFd( scriptPipe->writeFd );
2396 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2399 prog->sigStarted().connect( [&](){
2402 messagePipe->unrefWrite();
2403 scriptPipe->unrefWrite();
2406 prog->connectFunc( &zyppng::IODevice::sigChannelReadyRead, [&](
int channel ){
2407 while( prog->canReadLine( channel ) ) {
2408 L_ERR(
"zypp-rpm") << ( channel == zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2414 const auto outFd = prog->stdinFd();
2421 zyppng::rpc::HeaderSizeType msgSize =
commit.ByteSizeLong();
2422 const auto written = zyppng::eintrSafeCall( ::write, outFd, &msgSize,
sizeof(zyppng::rpc::HeaderSizeType) );
2423 if ( written !=
sizeof(zyppng::rpc::HeaderSizeType) ) {
2424 prog->stop( SIGKILL );
2428 zyppng::FileOutputStream fo ( outFd );
2429 if ( !
commit.SerializeToZeroCopyStream( &fo ) ) {
2430 prog->stop( SIGKILL );
2440 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd } ) )
2443 zyppng::rpc::HeaderSizeType pendingMessageSize = 0;
2444 const auto &processMessages = [&] ( ) {
2448 const auto &parseMsgWithStepId = [&steps](
const auto &m,
auto &p ){
2449 if ( !p.ParseFromString( m.value() ) ) {
2450 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2454 auto id = p.stepid();
2455 if ( id < 0 || id >= steps.size() ) {
2456 ERR <<
"Received invalid stepId: " <<
id <<
" in " << m.messagetypename() <<
" message from zypp-rpm, ignoring." << std::endl;
2462 while ( msgSource->bytesAvailable() ) {
2464 if ( pendingMessageSize == 0 ) {
2465 if ( std::size_t(msgSource->bytesAvailable()) >=
sizeof( zyppng::rpc::HeaderSizeType ) ) {
2466 msgSource->read(
reinterpret_cast<char *
>( &pendingMessageSize ),
sizeof( zyppng::rpc::HeaderSizeType ) );
2470 if ( msgSource->bytesAvailable() < pendingMessageSize ) {
2474 auto bytes = msgSource->read( pendingMessageSize );
2475 pendingMessageSize = 0;
2477 zypp::proto::Envelope m;
2478 if (! m.ParseFromArray( bytes.data(), bytes.size() ) ) {
2481 ERR <<
"Received misformed message from zypp-rpm, ignoring" << std::endl;
2489 const auto &mName = m.messagetypename();
2490 if ( mName ==
"zypp.proto.target.RpmLog" ) {
2493 if ( !p.ParseFromString( m.value() ) ) {
2494 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2497 ( p.level() >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2498 : p.level() >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2499 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p.level() <<
"> " << p.line();
2502 }
else if ( mName ==
"zypp.proto.target.PackageBegin" ) {
2503 finalizeCurrentReport();
2505 zpt::PackageBegin p;
2506 if ( !parseMsgWithStepId( m, p ) )
2509 aboutToStartNewReport();
2511 auto & step = steps.at( p.stepid() );
2512 currentStepId = p.stepid();
2514 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2515 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2517 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2518 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2521 }
else if ( mName ==
"zypp.proto.target.PackageFinished" ) {
2522 zpt::PackageFinished p;
2523 if ( !parseMsgWithStepId( m, p ) )
2526 if ( p.stepid() < 0 || p.stepid() > steps.size() )
2533 }
else if ( mName ==
"zypp.proto.target.PackageProgress" ) {
2534 zpt::PackageProgress p;
2535 if ( !parseMsgWithStepId( m, p ) )
2538 if ( uninstallreport )
2539 (*uninstallreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2540 else if ( installreport )
2541 (*installreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2543 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2545 }
else if ( mName ==
"zypp.proto.target.PackageError" ) {
2546 zpt::PackageError p;
2547 if ( !parseMsgWithStepId( m, p ) )
2550 if ( p.stepid() >= 0 && p.stepid() < steps.size() )
2553 finalizeCurrentReport();
2555 }
else if ( mName ==
"zypp.proto.target.ScriptBegin" ) {
2556 finalizeCurrentReport();
2559 if ( !p.ParseFromString( m.value() ) ) {
2560 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2564 aboutToStartNewReport();
2567 const auto stepId = p.stepid();
2568 if ( stepId >= 0 && stepId < steps.size() ) {
2572 currentStepId = p.stepid();
2573 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2574 currentScriptType = p.scripttype();
2575 currentScriptPackage = p.scriptpackage();
2576 (*scriptreport)->start( p.scripttype(), p.scriptpackage(), resPtr );
2578 }
else if ( mName ==
"zypp.proto.target.ScriptFinished" ) {
2582 }
else if ( mName ==
"zypp.proto.target.ScriptError" ) {
2585 if ( !p.ParseFromString( m.value() ) ) {
2586 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2591 const auto stepId = p.stepid();
2592 if ( stepId >= 0 && stepId < steps.size() ) {
2602 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2605 writeRpmMsgToHistory();
2607 if ( !scriptreport ) {
2608 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2617 scriptreport.reset();
2620 }
else if ( mName ==
"zypp.proto.target.CleanupBegin" ) {
2621 finalizeCurrentReport();
2623 zpt::CleanupBegin beg;
2624 if ( !beg.ParseFromString( m.value() ) ) {
2625 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2629 aboutToStartNewReport();
2630 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2631 (*cleanupreport)->start( beg.nvra() );
2632 }
else if ( mName ==
"zypp.proto.target.CleanupFinished" ) {
2634 finalizeCurrentReport();
2636 }
else if ( mName ==
"zypp.proto.target.CleanupProgress" ) {
2637 zpt::CleanupProgress prog;
2638 if ( !prog.ParseFromString( m.value() ) ) {
2639 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2643 if ( !cleanupreport ) {
2644 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2648 (*cleanupreport)->progress( prog.amount() );
2650 }
else if ( mName ==
"zypp.proto.target.TransBegin" ) {
2651 finalizeCurrentReport();
2653 zpt::TransBegin beg;
2654 if ( !beg.ParseFromString( m.value() ) ) {
2655 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2659 aboutToStartNewReport();
2660 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2661 (*transactionreport)->start( beg.name() );
2662 }
else if ( mName ==
"zypp.proto.target.TransFinished" ) {
2664 finalizeCurrentReport();
2666 }
else if ( mName ==
"zypp.proto.target.TransProgress" ) {
2667 zpt::TransProgress prog;
2668 if ( !prog.ParseFromString( m.value() ) ) {
2669 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2673 if ( !transactionreport ) {
2674 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2678 (*transactionreport)->progress( prog.amount() );
2679 }
else if ( mName ==
"zypp.proto.target.TransactionError" ) {
2681 zpt::TransactionError error;
2682 if ( !error.ParseFromString( m.value() ) ) {
2683 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2688 transactionError = std::move(error);
2691 ERR <<
"Received unexpected message from zypp-rpm: "<< m.messagetypename() <<
", ignoring" << std::endl;
2697 msgSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, processMessages );
2700 int zyppRpmExitCode = -1;
2701 prog->connectFunc( &zyppng::Process::sigFinished, [&](
int code ){
2702 zyppRpmExitCode = code;
2706 if ( !prog->start( argv ) ) {
2717 finalizeCurrentReport();
2720 bool readMsgs =
false;
2721 while( prog->canReadLine( zyppng::Process::StdErr ) ) {
2723 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdErr ).asStringView();
2725 while( prog->canReadLine( zyppng::Process::StdOut ) ) {
2727 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdOut ).asStringView();
2730 while ( scriptSource->canReadLine() ) {
2732 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2734 if ( scriptSource->bytesAvailable() > 0 ) {
2736 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2741 switch ( zyppRpmExitCode ) {
2743 case zypprpm::NoError:
2744 case zypprpm::RpmFinishedWithError:
2746 case zypprpm::RpmFinishedWithTransactionError: {
2748 if ( transactionError ) {
2750 std::ostringstream sstr;
2751 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2752 for (
const auto & err : transactionError->problems() ) {
2753 sstr <<
" " << err.message() <<
"\n";
2763 case zypprpm::FailedToOpenDb:
2766 case zypprpm::WrongHeaderSize:
2767 case zypprpm::WrongMessageFormat:
2770 case zypprpm::RpmInitFailed:
2773 case zypprpm::FailedToReadPackage:
2776 case zypprpm::FailedToAddStepToTransaction:
2779 case zypprpm::RpmOrderFailed:
2782 case zypprpm::FailedToCreateLock:
2787 for (
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2788 auto &step = steps[stepId];
2800 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2804 std::string referenceFilename( p->referenceFilename() );
2806 if ( referenceFilename.empty() ) {
2807 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2809 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2811 if ( !
rpm().hasFile( referencePath.asString() ) ) {
2815 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2817 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2831 if ( ! successfullyInstalledPackages.empty() )
2834 successfullyInstalledPackages, abort ) )
2836 WAR <<
"Commit aborted by the user" << endl;
2842 successfullyInstalledPackages,
2849 logPatchStatusChanges( result_r.
transaction(), *
this );
2877 if ( baseproduct.isFile() )
2890 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2895 inline Pathname staticGuessRoot(
const Pathname & root_r )
2897 if ( root_r.empty() )
2902 return Pathname(
"/");
2908 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2910 std::ifstream idfile( file_r.c_str() );
2911 for( iostr::EachLine in( idfile ); in; in.next() )
2914 if ( ! line.empty() )
2917 return std::string();
2928 if ( p->isTargetDistribution() )
2936 const Pathname needroot( staticGuessRoot(root_r) );
2937 const Target_constPtr target( getZYpp()->getTarget() );
2938 if ( target && target->root() == needroot )
2939 return target->requestedLocales();
2945 MIL <<
"updateAutoInstalled if changed..." << endl;
2953 {
return baseproductdata(
_root ).registerTarget(); }
2956 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
2959 {
return baseproductdata(
_root ).registerRelease(); }
2962 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
2965 {
return baseproductdata(
_root ).registerFlavor(); }
2968 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
3001 std::string
distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version();
3008 scoped_ptr<rpm::RpmDb> tmprpmdb;
3014 tmprpmdb->initDatabase( );
3031 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
3036 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
3042 std::string guessAnonymousUniqueId(
const Pathname & root_r )
3045 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
3046 if ( ret.
empty() && root_r !=
"/" )
3049 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
3057 return guessAnonymousUniqueId(
root() );
3062 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3069 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.
bool TRANSACTIONAL_UPDATE()
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.
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
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)