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/commit.pb.h>
70#include <zypp-proto/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 );
237 class AssertProcMounted
243 AssertProcMounted( Pathname root_r )
246 if ( ! PathInfo(root_r/
"self").isDir() ) {
247 MIL <<
"Try to make sure proc is mounted at" << root_r << endl;
249 && execute({
"mount",
"-t",
"proc",
"proc", root_r.asString() }) == 0 ) {
253 WAR <<
"Mounting proc at " << root_r <<
" failed" << endl;
258 ~AssertProcMounted( )
262 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
263 execute({
"umount",
"-l",
_mountpoint.asString() });
271 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
290 std::ifstream infile( historyFile_r.c_str() );
291 for( iostr::EachLine in( infile ); in; in.next() )
293 const char * ch( (*in).c_str() );
295 if ( *ch <
'1' ||
'9' < *ch )
297 const char * sep1 = ::strchr( ch,
'|' );
302 bool installs =
true;
303 if ( ::strncmp( sep1,
"install|", 8 ) )
305 if ( ::strncmp( sep1,
"remove |", 8 ) )
312 const char * sep2 = ::strchr( sep1,
'|' );
313 if ( !sep2 || sep1 == sep2 )
315 (*in)[sep2-ch] =
'\0';
316 IdString pkg( sep1 );
320 onSystemByUserList.erase( pkg );
324 if ( (sep1 = ::strchr( sep2+1,
'|' ))
325 && (sep1 = ::strchr( sep1+1,
'|' ))
326 && (sep2 = ::strchr( sep1+1,
'|' )) )
328 (*in)[sep2-ch] =
'\0';
329 if ( ::strchr( sep1+1,
'@' ) )
332 onSystemByUserList.insert( pkg );
337 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
338 return onSystemByUserList;
348 return PluginFrame( command_r, json::Object {
349 {
"TransactionStepList", steps_r }
359 MIL <<
"Testcases to keep: " << toKeep << endl;
365 WAR <<
"No Target no Testcase!" << endl;
369 std::string stem(
"updateTestcase" );
370 Pathname dir( target->assertRootPrefix(
"/var/log/") );
374 std::list<std::string> content;
376 std::set<std::string> cases;
377 for_( c, content.begin(), content.end() )
382 if ( cases.size() >= toKeep )
384 unsigned toDel = cases.size() - toKeep + 1;
385 for_( c, cases.begin(), cases.end() )
394 MIL <<
"Write new testcase " << next << endl;
395 getZYpp()->resolver()->createSolverTestcase( next.
asString(),
false );
412 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
422 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
427 WAR <<
"User request to abort script " << script_r << endl;
436 if ( prog.close() != 0 )
438 ret.second = report_r->problem( prog.execError() );
439 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
440 std::ostringstream sstr;
441 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
442 historylog.
comment(sstr.str(),
true);
454 bool executeScript(
const Pathname & root_r,
455 const Pathname & script_r,
456 callback::SendReport<PatchScriptReport> & report_r )
461 action = doExecuteScript( root_r, script_r, report_r );
465 switch ( action.second )
468 WAR <<
"User request to abort at script " << script_r << endl;
473 WAR <<
"User request to skip script " << script_r << endl;
483 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
492 bool RunUpdateScripts(
const Pathname & root_r,
493 const Pathname & scriptsPath_r,
494 const std::vector<sat::Solvable> & checkPackages_r,
497 if ( checkPackages_r.empty() )
500 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
502 if ( ! PathInfo( scriptsDir ).isDir() )
505 std::list<std::string> scripts;
507 if ( scripts.empty() )
515 std::map<std::string, Pathname> unify;
516 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
518 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
519 for_( sit, scripts.begin(), scripts.end() )
524 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
527 PathInfo script( scriptsDir / *sit );
528 Pathname localPath( scriptsPath_r/(*sit) );
529 std::string unifytag;
531 if ( script.isFile() )
537 else if ( ! script.isExist() )
545 if ( unifytag.empty() )
549 if ( unify[unifytag].empty() )
551 unify[unifytag] = localPath;
558 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
559 MIL <<
"Skip update script: " << msg << endl;
560 HistoryLog().comment( msg,
true );
564 if ( abort || aborting_r )
566 WAR <<
"Aborting: Skip update script " << *sit << endl;
567 HistoryLog().comment(
568 localPath.asString() +
_(
" execution skipped while aborting"),
573 MIL <<
"Found update script " << *sit << endl;
574 callback::SendReport<PatchScriptReport> report;
575 report->start( make<Package>( *it ), script.path() );
577 if ( ! executeScript( root_r, localPath, report ) )
589 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
591 std::ifstream infile( file_r.c_str() );
592 for( iostr::EachLine in( infile ); in; in.next() )
594 out_r << *in << endl;
598 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
600 std::string ret( cmd_r );
601#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
602 SUBST_IF(
"%p", notification_r.solvable().asString() );
603 SUBST_IF(
"%P", notification_r.file().asString() );
608 void sendNotification(
const Pathname & root_r,
611 if ( notifications_r.empty() )
615 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
616 if ( cmdspec.empty() )
620 if ( pos == std::string::npos )
622 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
623 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
628 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
630 enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
631 Format format = UNKNOWN;
632 if ( formatStr ==
"none" )
634 else if ( formatStr ==
"single" )
636 else if ( formatStr ==
"digest" )
638 else if ( formatStr ==
"bulk" )
642 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
643 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
651 if ( format == NONE || format == SINGLE )
653 for_( it, notifications_r.begin(), notifications_r.end() )
655 std::vector<std::string> command;
656 if ( format == SINGLE )
658 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
663 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
667 int ret = prog.close();
670 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
671 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
677 else if ( format == DIGEST || format == BULK )
679 filesystem::TmpFile tmpfile;
680 std::ofstream out( tmpfile.path().c_str() );
681 for_( it, notifications_r.begin(), notifications_r.end() )
683 if ( format == DIGEST )
685 out << it->file() << endl;
687 else if ( format == BULK )
693 std::vector<std::string> command;
694 command.push_back(
"<"+tmpfile.path().asString() );
695 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
700 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
704 int ret = prog.close();
707 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
708 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
715 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
716 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
727 void RunUpdateMessages(
const Pathname & root_r,
728 const Pathname & messagesPath_r,
729 const std::vector<sat::Solvable> & checkPackages_r,
730 ZYppCommitResult & result_r )
732 if ( checkPackages_r.empty() )
735 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
737 if ( ! PathInfo( messagesDir ).isDir() )
740 std::list<std::string> messages;
742 if ( messages.empty() )
748 HistoryLog historylog;
749 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
751 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
752 for_( sit, messages.begin(), messages.end() )
757 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
760 PathInfo message( messagesDir / *sit );
761 if ( ! message.isFile() || message.size() == 0 )
764 MIL <<
"Found update message " << *sit << endl;
765 Pathname localPath( messagesPath_r/(*sit) );
766 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
767 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
770 sendNotification( root_r, result_r.updateMessages() );
776 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
779 if ( changedPseudoInstalled.empty() )
787 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
793 HistoryLog historylog;
794 for (
const auto & el : changedPseudoInstalled )
795 historylog.patchStateChange( el.first, el.second );
804 const std::vector<sat::Solvable> & checkPackages_r,
806 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
819 , _requestedLocalesFile( home() /
"RequestedLocales" )
820 , _autoInstalledFile( home() /
"AutoInstalled" )
829 sigMultiversionSpecChanged();
830 MIL <<
"Initialized target on " <<
_root << endl;
838 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
848 boost::function<
bool ()> condition,
849 boost::function<std::string ()> value )
851 std::string val = value();
859 MIL <<
"updating '" << filename <<
"' content." << endl;
863 std::ofstream filestr;
866 filestr.open( filename.
c_str() );
868 if ( filestr.good() )
904 WAR <<
"Can't create anonymous id file" << endl;
913 Pathname flavorpath(
home() /
"LastDistributionFlavor");
919 WAR <<
"No base product, I won't create flavor cache" << endl;
923 std::string flavor = p->flavor();
935 WAR <<
"Can't create flavor cache" << endl;
948 sigMultiversionSpecChanged();
949 MIL <<
"Targets closed" << endl;
973 Pathname rpmsolvcookie = base/
"cookie";
975 bool build_rpm_solv =
true;
985 MIL <<
"Read cookie: " << cookie << endl;
990 if ( status == rpmstatus )
991 build_rpm_solv =
false;
992 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
993 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
997 if ( build_rpm_solv )
1011 bool switchingToTmpSolvfile =
false;
1012 Exception ex(
"Failed to cache rpm database.");
1018 rpmsolv = base/
"solv";
1019 rpmsolvcookie = base/
"cookie";
1026 WAR <<
"Using a temporary solv file at " << base << endl;
1027 switchingToTmpSolvfile =
true;
1036 if ( ! switchingToTmpSolvfile )
1046 cmd.push_back(
"rpmdb2solv" );
1048 cmd.push_back(
"-r" );
1051 cmd.push_back(
"-D" );
1053 cmd.push_back(
"-X" );
1055 cmd.push_back(
"-p" );
1058 if ( ! oldSolvFile.
empty() )
1059 cmd.push_back( oldSolvFile.
asString() );
1061 cmd.push_back(
"-o" );
1065 std::string errdetail;
1068 WAR <<
" " << output;
1069 if ( errdetail.empty() ) {
1073 errdetail += output;
1076 int ret = prog.
close();
1097 if (
root() ==
"/" )
1108 if ( !
PathInfo(base/
"solv.idx").isExist() )
1111 return build_rpm_solv;
1129 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1130 ", force loading: " << (force?
"true":
"false") << endl;
1135 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1142 if ( newCache || force )
1159 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1165 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1190 if (
PathInfo( historyFile ).isExist() )
1197 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1198 onSystemByAuto.insert( ident );
1219 if (
PathInfo( needrebootFile ).isFile() )
1220 needrebootSpec.
parseFrom( needrebootFile );
1223 if (
PathInfo( needrebootDir ).isDir() )
1228 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1230 if ( ! isRpmConfigBackup( str_r ) )
1232 Pathname needrebootFile { needrebootDir / str_r };
1233 if (
PathInfo( needrebootFile ).isFile() )
1234 needrebootSpec.
parseFrom( needrebootFile );
1245 if ( ! hardLocks.empty() )
1254 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1266 bool explicitDryRun = policy_r.
dryRun();
1276 if (
root() ==
"/" )
1290 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1309 steps.push_back( *it );
1316 MIL <<
"Todo: " << result << endl;
1326 if ( commitPlugins )
1327 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1334 if ( ! policy_r.
dryRun() )
1340 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1347 if ( ! policy_r.
dryRun() )
1369 DBG <<
"dryRun: Not storing non-package data." << endl;
1376 if ( ! policy_r.
dryRun() )
1378 for_( it, steps.begin(), steps.end() )
1380 if ( ! it->satSolvable().isKind<
Patch>() )
1388 if ( ! patch ||patch->message().empty() )
1391 MIL <<
"Show message for " << patch << endl;
1393 if ( ! report->show( patch ) )
1395 WAR <<
"commit aborted by the user" << endl;
1402 DBG <<
"dryRun: Not checking patch messages." << endl;
1424 for_( it, steps.begin(), steps.end() )
1426 switch ( it->stepType() )
1445 localfile = packageCache.
get( pi );
1448 catch (
const AbortRequestException & exp )
1452 WAR <<
"commit cache preload aborted by the user" << endl;
1456 catch (
const SkipRequestException & exp )
1461 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1471 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1481 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1485 if ( ! policy_r.
dryRun() )
1492 commit( policy_r, packageCache, result );
1497 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1498 if ( explicitDryRun ) {
1512 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1513 if ( explicitDryRun ) {
1525 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1534 if ( commitPlugins )
1535 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1540 if ( ! policy_r.
dryRun() )
1545 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1556 struct NotifyAttemptToModify
1574 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1579 NotifyAttemptToModify attemptToModify( result_r );
1584 AssertProcMounted assertProcMounted(
_root );
1587 std::vector<sat::Solvable> successfullyInstalledPackages;
1590 for_( step, steps.begin(), steps.end() )
1612 localfile = packageCache_r.
get( citem );
1614 catch (
const AbortRequestException &e )
1616 WAR <<
"commit aborted by the user" << endl;
1621 catch (
const SkipRequestException &e )
1624 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1633 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1642 bool success =
false;
1670 WAR <<
"commit aborted by the user" << endl;
1679 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1695 WAR <<
"dry run failed" << endl;
1702 WAR <<
"commit aborted by the user" << endl;
1707 WAR <<
"Install failed" << endl;
1713 if ( success && !policy_r.
dryRun() )
1716 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1725 bool success =
false;
1738 WAR <<
"commit aborted by the user" << endl;
1754 WAR <<
"commit aborted by the user" << endl;
1760 WAR <<
"removal of " << p <<
" failed";
1763 if ( success && !policy_r.
dryRun() )
1770 else if ( ! policy_r.
dryRun() )
1774 if ( ! citem.
buddy() )
1781 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1787 std::string referenceFilename( p->referenceFilename() );
1788 if ( referenceFilename.empty() )
1790 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1794 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1795 if ( !
rpm().hasFile( referencePath.asString() ) )
1800 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1804 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1831 if ( ! successfullyInstalledPackages.empty() )
1834 successfullyInstalledPackages, abort ) )
1836 WAR <<
"Commit aborted by the user" << endl;
1842 successfullyInstalledPackages,
1849 logPatchStatusChanges( result_r.
transaction(), *
this );
1868 void sendLogline(
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
1871 data.
set(
"line", std::cref(line_r) );
1872 data.set(
"level", level_r );
1878 auto u2rpmlevel = [](
unsigned rpmlevel_r ) -> ReportType::loglevel {
1879 switch ( rpmlevel_r ) {
1880 case RPMLOG_EMERG: [[fallthrough]];
1881 case RPMLOG_ALERT: [[fallthrough]];
1883 return ReportType::loglevel::crt;
1885 return ReportType::loglevel::err;
1886 case RPMLOG_WARNING:
1887 return ReportType::loglevel::war;
1888 default: [[fallthrough]];
1889 case RPMLOG_NOTICE: [[fallthrough]];
1891 return ReportType::loglevel::msg;
1893 return ReportType::loglevel::dbg;
1901 { (*this)->report( userData_r ); }
1914 namespace zpt = zypp::proto::target;
1920 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1925 NotifyAttemptToModify attemptToModify( result_r );
1931 AssertProcMounted assertProcMounted(
_root );
1946 commit.set_flags( flags );
1954 for (
auto &[
_, value] : data ) {
1956 value.resetDispose();
1963 auto &step = steps[stepId];
1980 locCache.value()[stepId] = packageCache_r.
get( citem );
1982 zpt::TransactionStep tStep;
1983 tStep.set_stepid( stepId );
1984 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
1985 tStep.mutable_install()->set_multiversion( p->multiversionInstall() );
1987 *
commit.mutable_steps()->Add( ) = std::move(tStep);
1989 catch (
const AbortRequestException &e )
1991 WAR <<
"commit aborted by the user" << endl;
1996 catch (
const SkipRequestException &e )
1999 WAR <<
"Skipping package " << p <<
" in commit" << endl;
2008 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2014 zpt::TransactionStep tStep;
2015 tStep.set_stepid( stepId );
2016 tStep.mutable_remove()->set_name( p->name() );
2017 tStep.mutable_remove()->set_version( p->edition().version() );
2018 tStep.mutable_remove()->set_release( p->edition().release() );
2019 tStep.mutable_remove()->set_arch( p->arch().asString() );
2021 *
commit.mutable_steps()->Add() = std::move(tStep);
2032 zpt::TransactionStep tStep;
2033 tStep.set_stepid( stepId );
2034 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
2035 tStep.mutable_install()->set_multiversion(
false );
2036 *
commit.mutable_steps()->Add() = std::move(tStep);
2040 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
2047 std::vector<sat::Solvable> successfullyInstalledPackages;
2049 if (
commit.steps_size() ) {
2052 auto loop = zyppng::EventLoop::create();
2061 int currentStepId = -1;
2067 bool gotEndOfScript =
false;
2070 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2071 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2072 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2073 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2074 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2077 std::optional<zpt::TransactionError> transactionError;
2080 std::string currentScriptType;
2081 std::string currentScriptPackage;
2091 unsigned lineno = 0;
2094 auto msgSource = zyppng::AsyncDataSource::create();
2095 auto scriptSource = zyppng::AsyncDataSource::create();
2100 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2102 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2104 if ( currentStepId >= 0 )
2105 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2106 cmdout.
set(
"line", line );
2110 if ( installreport ) {
2112 }
else if ( uninstallreport ) {
2114 }
else if ( scriptreport ) {
2116 }
else if ( transactionreport ) {
2118 }
else if ( cleanupreport ) {
2121 WAR <<
"Got rpm output without active report " << line;
2126 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2130 if ( line.back() !=
'\n' )
2136 const auto &processDataFromScriptFd = [&](){
2138 while ( scriptSource->canReadLine() ) {
2140 if ( gotEndOfScript )
2143 std::string l = scriptSource->readLine().asString();
2145 gotEndOfScript =
true;
2149 l = l.substr( 0, rawsize );
2151 L_DBG(
"zypp-rpm") <<
"[rpm> " << l;
2152 sendRpmLineToReport( l );
2155 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2158 const auto &waitForScriptEnd = [&]() {
2161 if ( gotEndOfScript )
2165 processDataFromScriptFd();
2168 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2171 scriptSource->waitForReadyRead( 100 );
2175 const auto &aboutToStartNewReport = [&](){
2177 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2178 ERR <<
"There is still a running report, this is a bug" << std::endl;
2182 gotEndOfScript =
false;
2185 const auto &writeRpmMsgToHistory = [&](){
2186 if ( rpmmsg.size() == 0 )
2190 rpmmsg +=
"[truncated]\n";
2192 std::ostringstream sstr;
2193 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2198 const auto &finalizeCurrentReport = [&]() {
2201 if ( currentStepId >= 0 ) {
2202 step = &steps.at(currentStepId);
2206 if ( installreport ) {
2214 writeRpmMsgToHistory();
2218 ( *installreport)->progress( 100, resObj );
2221 if ( currentStepId >= 0 )
2222 locCache.value().erase( currentStepId );
2223 successfullyInstalledPackages.push_back( step->
satSolvable() );
2229 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2241 writeRpmMsgToHistory();
2244 if ( uninstallreport ) {
2252 writeRpmMsgToHistory();
2256 ( *uninstallreport)->progress( 100, resObj );
2266 writeRpmMsgToHistory();
2269 if ( scriptreport ) {
2271 ( *scriptreport)->progress( 100, resObj );
2274 if ( transactionreport ) {
2276 ( *transactionreport)->progress( 100 );
2279 if ( cleanupreport ) {
2281 ( *cleanupreport)->progress( 100 );
2287 currentScriptType.clear();
2288 currentScriptPackage.clear();
2289 installreport.reset();
2290 uninstallreport.reset();
2291 scriptreport.reset();
2292 transactionreport.reset();
2293 cleanupreport.reset();
2303 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2305 const char *argv[] = {
2308 zyppRpmBinary.data(),
2311 auto prog = zyppng::Process::create();
2315 auto messagePipe = zyppng::Pipe::create();
2321 auto scriptPipe = zyppng::Pipe::create();
2325 prog->addFd( messagePipe->writeFd );
2326 prog->addFd( scriptPipe->writeFd );
2329 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2332 prog->sigStarted().connect( [&](){
2335 messagePipe->unrefWrite();
2336 scriptPipe->unrefWrite();
2339 prog->connectFunc( &zyppng::IODevice::sigChannelReadyRead, [&](
int channel ){
2340 while( prog->canReadLine( channel ) ) {
2341 L_ERR(
"zypp-rpm") << ( channel == zyppng::Process::StdOut ?
"<stdout> " :
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();
2347 const auto outFd = prog->stdinFd();
2354 zyppng::rpc::HeaderSizeType msgSize =
commit.ByteSizeLong();
2355 const auto written = zyppng::eintrSafeCall(
::write, outFd, &msgSize,
sizeof(zyppng::rpc::HeaderSizeType) );
2356 if ( written !=
sizeof(zyppng::rpc::HeaderSizeType) ) {
2357 prog->stop( SIGKILL );
2361 zyppng::FileOutputStream fo ( outFd );
2362 if ( !
commit.SerializeToZeroCopyStream( &fo ) ) {
2363 prog->stop( SIGKILL );
2373 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd } ) )
2376 zyppng::rpc::HeaderSizeType pendingMessageSize = 0;
2377 const auto &processMessages = [&] ( ) {
2381 const auto &parseMsgWithStepId = [&steps](
const auto &m,
auto &p ){
2382 if ( !p.ParseFromString( m.value() ) ) {
2383 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2387 auto id = p.stepid();
2388 if ( id < 0 || id >= steps.size() ) {
2389 ERR <<
"Received invalid stepId: " <<
id <<
" in " << m.messagetypename() <<
" message from zypp-rpm, ignoring." << std::endl;
2395 while ( msgSource->bytesAvailable() ) {
2397 if ( pendingMessageSize == 0 ) {
2398 if ( std::size_t(msgSource->bytesAvailable()) >=
sizeof( zyppng::rpc::HeaderSizeType ) ) {
2399 msgSource->read(
reinterpret_cast<char *
>( &pendingMessageSize ),
sizeof( zyppng::rpc::HeaderSizeType ) );
2403 if ( msgSource->bytesAvailable() < pendingMessageSize ) {
2407 auto bytes = msgSource->read( pendingMessageSize );
2408 pendingMessageSize = 0;
2410 zypp::proto::Envelope m;
2411 if (! m.ParseFromArray( bytes.data(), bytes.size() ) ) {
2414 ERR <<
"Received misformed message from zypp-rpm, ignoring" << std::endl;
2422 const auto &mName = m.messagetypename();
2423 if ( mName ==
"zypp.proto.target.RpmLog" ) {
2426 if ( !p.ParseFromString( m.value() ) ) {
2427 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2430 ( p.level() >= RPMLOG_ERR ?
L_ERR(
"zypp-rpm")
2431 : p.level() >= RPMLOG_WARNING ?
L_WAR(
"zypp-rpm")
2432 :
L_DBG(
"zypp-rpm") ) <<
"[rpm " << p.level() <<
"> " << p.line();
2435 }
else if ( mName ==
"zypp.proto.target.PackageBegin" ) {
2436 finalizeCurrentReport();
2438 zpt::PackageBegin p;
2439 if ( !parseMsgWithStepId( m, p ) )
2442 aboutToStartNewReport();
2444 auto & step = steps.at( p.stepid() );
2445 currentStepId = p.stepid();
2447 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2448 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2450 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2451 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2454 }
else if ( mName ==
"zypp.proto.target.PackageFinished" ) {
2455 zpt::PackageFinished p;
2456 if ( !parseMsgWithStepId( m, p ) )
2459 if ( p.stepid() < 0 || p.stepid() > steps.size() )
2466 }
else if ( mName ==
"zypp.proto.target.PackageProgress" ) {
2467 zpt::PackageProgress p;
2468 if ( !parseMsgWithStepId( m, p ) )
2471 if ( uninstallreport )
2472 (*uninstallreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2473 else if ( installreport )
2474 (*installreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2476 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2478 }
else if ( mName ==
"zypp.proto.target.PackageError" ) {
2479 zpt::PackageError p;
2480 if ( !parseMsgWithStepId( m, p ) )
2483 if ( p.stepid() >= 0 && p.stepid() < steps.size() )
2486 finalizeCurrentReport();
2488 }
else if ( mName ==
"zypp.proto.target.ScriptBegin" ) {
2489 finalizeCurrentReport();
2492 if ( !p.ParseFromString( m.value() ) ) {
2493 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2497 aboutToStartNewReport();
2500 const auto stepId = p.stepid();
2501 if ( stepId >= 0 && stepId < steps.size() ) {
2505 currentStepId = p.stepid();
2506 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2507 currentScriptType = p.scripttype();
2508 currentScriptPackage = p.scriptpackage();
2509 (*scriptreport)->start( p.scripttype(), p.scriptpackage(), resPtr );
2511 }
else if ( mName ==
"zypp.proto.target.ScriptFinished" ) {
2515 }
else if ( mName ==
"zypp.proto.target.ScriptError" ) {
2518 if ( !p.ParseFromString( m.value() ) ) {
2519 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2524 const auto stepId = p.stepid();
2525 if ( stepId >= 0 && stepId < steps.size() ) {
2535 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2538 writeRpmMsgToHistory();
2540 if ( !scriptreport ) {
2541 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2550 scriptreport.reset();
2553 }
else if ( mName ==
"zypp.proto.target.CleanupBegin" ) {
2554 finalizeCurrentReport();
2556 zpt::CleanupBegin beg;
2557 if ( !beg.ParseFromString( m.value() ) ) {
2558 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2562 aboutToStartNewReport();
2563 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2564 (*cleanupreport)->start( beg.nvra() );
2565 }
else if ( mName ==
"zypp.proto.target.CleanupFinished" ) {
2567 finalizeCurrentReport();
2569 }
else if ( mName ==
"zypp.proto.target.CleanupProgress" ) {
2570 zpt::CleanupProgress prog;
2571 if ( !prog.ParseFromString( m.value() ) ) {
2572 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2576 if ( !cleanupreport ) {
2577 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2581 (*cleanupreport)->progress( prog.amount() );
2583 }
else if ( mName ==
"zypp.proto.target.TransBegin" ) {
2584 finalizeCurrentReport();
2586 zpt::TransBegin beg;
2587 if ( !beg.ParseFromString( m.value() ) ) {
2588 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2592 aboutToStartNewReport();
2593 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2594 (*transactionreport)->start( beg.name() );
2595 }
else if ( mName ==
"zypp.proto.target.TransFinished" ) {
2597 finalizeCurrentReport();
2599 }
else if ( mName ==
"zypp.proto.target.TransProgress" ) {
2600 zpt::TransProgress prog;
2601 if ( !prog.ParseFromString( m.value() ) ) {
2602 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2606 if ( !transactionreport ) {
2607 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2611 (*transactionreport)->progress( prog.amount() );
2612 }
else if ( mName ==
"zypp.proto.target.TransactionError" ) {
2614 zpt::TransactionError error;
2615 if ( !error.ParseFromString( m.value() ) ) {
2616 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2621 transactionError = std::move(error);
2624 ERR <<
"Received unexpected message from zypp-rpm: "<< m.messagetypename() <<
", ignoring" << std::endl;
2630 msgSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, processMessages );
2633 int zyppRpmExitCode = -1;
2634 prog->connectFunc( &zyppng::Process::sigFinished, [&](
int code ){
2635 zyppRpmExitCode = code;
2639 if ( !prog->start( argv ) ) {
2650 finalizeCurrentReport();
2653 bool readMsgs =
false;
2654 while( prog->canReadLine( zyppng::Process::StdErr ) ) {
2656 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdErr ).asStringView();
2658 while( prog->canReadLine( zyppng::Process::StdOut ) ) {
2660 MIL <<
"zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdOut ).asStringView();
2663 while ( scriptSource->canReadLine() ) {
2665 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2667 if ( scriptSource->bytesAvailable() > 0 ) {
2669 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2674 switch ( zyppRpmExitCode ) {
2676 case zypprpm::NoError:
2677 case zypprpm::RpmFinishedWithError:
2679 case zypprpm::RpmFinishedWithTransactionError: {
2681 if ( transactionError ) {
2683 std::ostringstream sstr;
2684 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2685 for (
const auto & err : transactionError->problems() ) {
2686 sstr <<
" " << err.message() <<
"\n";
2696 case zypprpm::FailedToOpenDb:
2699 case zypprpm::WrongHeaderSize:
2700 case zypprpm::WrongMessageFormat:
2703 case zypprpm::RpmInitFailed:
2706 case zypprpm::FailedToReadPackage:
2709 case zypprpm::FailedToAddStepToTransaction:
2712 case zypprpm::RpmOrderFailed:
2718 auto &step = steps[stepId];
2730 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2734 std::string referenceFilename( p->referenceFilename() );
2736 if ( referenceFilename.empty() ) {
2737 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2739 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2741 if ( !
rpm().hasFile( referencePath.asString() ) ) {
2745 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2747 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2761 if ( ! successfullyInstalledPackages.empty() )
2764 successfullyInstalledPackages, abort ) )
2766 WAR <<
"Commit aborted by the user" << endl;
2772 successfullyInstalledPackages,
2779 logPatchStatusChanges( result_r.
transaction(), *
this );
2807 if ( baseproduct.isFile() )
2820 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2825 inline Pathname staticGuessRoot(
const Pathname & root_r )
2827 if ( root_r.empty() )
2832 return Pathname(
"/");
2838 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2840 std::ifstream idfile( file_r.c_str() );
2841 for( iostr::EachLine in( idfile ); in; in.next() )
2844 if ( ! line.empty() )
2847 return std::string();
2858 if ( p->isTargetDistribution() )
2866 const Pathname needroot( staticGuessRoot(root_r) );
2867 const Target_constPtr target( getZYpp()->getTarget() );
2868 if ( target && target->root() == needroot )
2869 return target->requestedLocales();
2875 MIL <<
"updateAutoInstalled if changed..." << endl;
2883 {
return baseproductdata(
_root ).registerTarget(); }
2886 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
2889 {
return baseproductdata(
_root ).registerRelease(); }
2892 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
2895 {
return baseproductdata(
_root ).registerFlavor(); }
2898 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
2931 std::string
distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version();
2938 scoped_ptr<rpm::RpmDb> tmprpmdb;
2944 tmprpmdb->initDatabase( );
2961 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
2966 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
2972 std::string guessAnonymousUniqueId(
const Pathname & root_r )
2975 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
2976 if ( ret.
empty() && root_r !=
"/" )
2979 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
2987 return guessAnonymousUniqueId(
root() );
2992 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
2999 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.