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>
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"
87#include <solv/repo_rpmdb.h>
88#include <solv/chksum.h>
98 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) ->
void {
99 ::solv_chksum_free( chk,
nullptr );
101 if ( ::rpm_hash_database_state( state, chk ) == 0 )
104 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
108 WAR <<
"rpm_hash_database_state failed" << endl;
128 inline void sigMultiversionSpecChanged()
146 for (
const Transaction::Step & step : steps_r )
148 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
158 static const std::string strType(
"type" );
159 static const std::string strStage(
"stage" );
160 static const std::string strSolvable(
"solvable" );
162 static const std::string strTypeDel(
"-" );
163 static const std::string strTypeIns(
"+" );
164 static const std::string strTypeMul(
"M" );
166 static const std::string strStageDone(
"ok" );
167 static const std::string strStageFailed(
"err" );
169 static const std::string strSolvableN(
"n" );
170 static const std::string strSolvableE(
"e" );
171 static const std::string strSolvableV(
"v" );
172 static const std::string strSolvableR(
"r" );
173 static const std::string strSolvableA(
"a" );
180 case Transaction::TRANSACTION_IGNORE:
break;
181 case Transaction::TRANSACTION_ERASE: ret.
add( strType, strTypeDel );
break;
182 case Transaction::TRANSACTION_INSTALL: ret.
add( strType, strTypeIns );
break;
183 case Transaction::TRANSACTION_MULTIINSTALL: ret.
add( strType, strTypeMul );
break;
188 case Transaction::STEP_TODO:
break;
189 case Transaction::STEP_DONE: ret.
add( strStage, strStageDone );
break;
190 case Transaction::STEP_ERROR: ret.
add( strStage, strStageFailed );
break;
199 ident = solv.ident();
206 ident = step_r.
ident();
208 arch = step_r.
arch();
213 { strSolvableV, ed.
version() },
214 { strSolvableR, ed.
release() },
218 s.add( strSolvableE, epoch );
220 ret.
add( strSolvable, s );
236 class AssertProcMounted
242 AssertProcMounted( Pathname root_r )
245 if ( ! PathInfo(root_r/
"self").isDir() ) {
246 MIL <<
"Try to make sure proc is mounted at" <<
_mountpoint << endl;
248 && execute({
"mount",
"-t",
"proc",
"proc", root_r.asString() }) == 0 ) {
257 ~AssertProcMounted( )
261 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
262 execute({
"umount",
"-l",
_mountpoint.asString() });
270 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
289 std::ifstream infile( historyFile_r.c_str() );
290 for( iostr::EachLine in( infile ); in; in.next() )
292 const char * ch( (*in).c_str() );
294 if ( *ch <
'1' ||
'9' < *ch )
296 const char * sep1 = ::strchr( ch,
'|' );
301 bool installs =
true;
302 if ( ::strncmp( sep1,
"install|", 8 ) )
304 if ( ::strncmp( sep1,
"remove |", 8 ) )
311 const char * sep2 = ::strchr( sep1,
'|' );
312 if ( !sep2 || sep1 == sep2 )
314 (*in)[sep2-ch] =
'\0';
315 IdString pkg( sep1 );
319 onSystemByUserList.erase( pkg );
323 if ( (sep1 = ::strchr( sep2+1,
'|' ))
324 && (sep1 = ::strchr( sep1+1,
'|' ))
325 && (sep2 = ::strchr( sep1+1,
'|' )) )
327 (*in)[sep2-ch] =
'\0';
328 if ( ::strchr( sep1+1,
'@' ) )
331 onSystemByUserList.insert( pkg );
336 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
337 return onSystemByUserList;
347 return PluginFrame( command_r, json::Object {
348 {
"TransactionStepList", steps_r }
358 MIL <<
"Testcases to keep: " << toKeep << endl;
361 Target_Ptr target( getZYpp()->getTarget() );
364 WAR <<
"No Target no Testcase!" << endl;
368 std::string stem(
"updateTestcase" );
369 Pathname dir( target->assertRootPrefix(
"/var/log/") );
373 std::list<std::string> content;
375 std::set<std::string> cases;
376 for_( c, content.begin(), content.end() )
381 if ( cases.size() >= toKeep )
383 unsigned toDel = cases.size() - toKeep + 1;
384 for_( c, cases.begin(), cases.end() )
393 MIL <<
"Write new testcase " << next << endl;
394 getZYpp()->resolver()->createSolverTestcase( next.
asString(),
false );
411 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
421 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
426 WAR <<
"User request to abort script " << script_r << endl;
435 if ( prog.close() != 0 )
437 ret.second = report_r->problem( prog.execError() );
438 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
439 std::ostringstream sstr;
440 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
441 historylog.
comment(sstr.str(),
true);
453 bool executeScript(
const Pathname & root_r,
454 const Pathname & script_r,
455 callback::SendReport<PatchScriptReport> & report_r )
460 action = doExecuteScript( root_r, script_r, report_r );
464 switch ( action.second )
467 WAR <<
"User request to abort at script " << script_r << endl;
472 WAR <<
"User request to skip script " << script_r << endl;
482 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
491 bool RunUpdateScripts(
const Pathname & root_r,
492 const Pathname & scriptsPath_r,
493 const std::vector<sat::Solvable> & checkPackages_r,
496 if ( checkPackages_r.empty() )
499 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
501 if ( ! PathInfo( scriptsDir ).isDir() )
504 std::list<std::string> scripts;
506 if ( scripts.empty() )
514 std::map<std::string, Pathname> unify;
515 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
517 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
518 for_( sit, scripts.begin(), scripts.end() )
523 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
526 PathInfo script( scriptsDir / *sit );
527 Pathname localPath( scriptsPath_r/(*sit) );
528 std::string unifytag;
530 if ( script.isFile() )
536 else if ( ! script.isExist() )
544 if ( unifytag.empty() )
548 if ( unify[unifytag].empty() )
550 unify[unifytag] = localPath;
557 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
558 MIL <<
"Skip update script: " << msg << endl;
559 HistoryLog().comment( msg,
true );
563 if ( abort || aborting_r )
565 WAR <<
"Aborting: Skip update script " << *sit << endl;
566 HistoryLog().comment(
567 localPath.asString() +
_(
" execution skipped while aborting"),
572 MIL <<
"Found update script " << *sit << endl;
573 callback::SendReport<PatchScriptReport> report;
574 report->start( make<Package>( *it ), script.path() );
576 if ( ! executeScript( root_r, localPath, report ) )
588 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
590 std::ifstream infile( file_r.c_str() );
591 for( iostr::EachLine in( infile ); in; in.next() )
593 out_r << *in << endl;
597 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
599 std::string ret( cmd_r );
600#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
601 SUBST_IF(
"%p", notification_r.solvable().asString() );
602 SUBST_IF(
"%P", notification_r.file().asString() );
607 void sendNotification(
const Pathname & root_r,
610 if ( notifications_r.empty() )
614 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
615 if ( cmdspec.empty() )
619 if ( pos == std::string::npos )
621 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
622 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
627 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
629 enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
630 Format format = UNKNOWN;
631 if ( formatStr ==
"none" )
633 else if ( formatStr ==
"single" )
635 else if ( formatStr ==
"digest" )
637 else if ( formatStr ==
"bulk" )
641 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
642 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
650 if ( format == NONE || format == SINGLE )
652 for_( it, notifications_r.begin(), notifications_r.end() )
654 std::vector<std::string> command;
655 if ( format == SINGLE )
657 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
662 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
666 int ret = prog.close();
669 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
670 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
676 else if ( format == DIGEST || format == BULK )
678 filesystem::TmpFile tmpfile;
679 std::ofstream out( tmpfile.path().c_str() );
680 for_( it, notifications_r.begin(), notifications_r.end() )
682 if ( format == DIGEST )
684 out << it->file() << endl;
686 else if ( format == BULK )
692 std::vector<std::string> command;
693 command.push_back(
"<"+tmpfile.path().asString() );
694 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
699 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
703 int ret = prog.close();
706 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
707 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
714 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
715 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
726 void RunUpdateMessages(
const Pathname & root_r,
727 const Pathname & messagesPath_r,
728 const std::vector<sat::Solvable> & checkPackages_r,
729 ZYppCommitResult & result_r )
731 if ( checkPackages_r.empty() )
734 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
736 if ( ! PathInfo( messagesDir ).isDir() )
739 std::list<std::string> messages;
741 if ( messages.empty() )
747 HistoryLog historylog;
748 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
750 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
751 for_( sit, messages.begin(), messages.end() )
756 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
759 PathInfo message( messagesDir / *sit );
760 if ( ! message.isFile() || message.size() == 0 )
763 MIL <<
"Found update message " << *sit << endl;
764 Pathname localPath( messagesPath_r/(*sit) );
765 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
766 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
769 sendNotification( root_r, result_r.updateMessages() );
775 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
778 if ( changedPseudoInstalled.empty() )
786 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
792 HistoryLog historylog;
793 for (
const auto & el : changedPseudoInstalled )
794 historylog.patchStateChange( el.first, el.second );
803 const std::vector<sat::Solvable> & checkPackages_r,
805 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
818 , _requestedLocalesFile( home() /
"RequestedLocales" )
819 , _autoInstalledFile( home() /
"AutoInstalled" )
831 sigMultiversionSpecChanged();
832 MIL <<
"Initialized target on " <<
_root << endl;
839 static std::string generateRandomId()
841 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
850 void updateFileContent(
const Pathname &filename,
851 boost::function<
bool ()> condition,
852 boost::function<std::string ()> value )
854 std::string val = value();
862 MIL <<
"updating '" << filename <<
"' content." << endl;
866 std::ofstream filestr;
869 filestr.open( filename.
c_str() );
871 if ( filestr.good() )
885 static bool fileMissing(
const Pathname &pathname )
887 return ! PathInfo(pathname).isExist();
890 void TargetImpl::createAnonymousId()
const
897 Pathname idpath(
home() /
"AnonymousUniqueId");
901 updateFileContent( idpath,
902 boost::bind(fileMissing, idpath),
905 catch (
const Exception &e )
907 WAR <<
"Can't create anonymous id file" << endl;
912 void TargetImpl::createLastDistributionFlavorCache()
const
916 Pathname flavorpath(
home() /
"LastDistributionFlavor");
922 WAR <<
"No base product, I won't create flavor cache" << endl;
926 std::string flavor = p->flavor();
931 updateFileContent( flavorpath,
933 functor::Constant<bool>( ! flavor.empty() ),
934 functor::Constant<std::string>(flavor) );
936 catch (
const Exception &e )
938 WAR <<
"Can't create flavor cache" << endl;
952 sigMultiversionSpecChanged();
953 MIL <<
"Targets closed" << endl;
977 Pathname rpmsolvcookie = base/
"cookie";
979 bool build_rpm_solv =
true;
989 MIL <<
"Read cookie: " << cookie << endl;
994 if ( status == rpmstatus )
995 build_rpm_solv =
false;
996 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
997 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
1001 if ( build_rpm_solv )
1015 bool switchingToTmpSolvfile =
false;
1016 Exception ex(
"Failed to cache rpm database.");
1022 rpmsolv = base/
"solv";
1023 rpmsolvcookie = base/
"cookie";
1030 WAR <<
"Using a temporary solv file at " << base << endl;
1031 switchingToTmpSolvfile =
true;
1040 if ( ! switchingToTmpSolvfile )
1050 cmd.push_back(
"rpmdb2solv" );
1052 cmd.push_back(
"-r" );
1055 cmd.push_back(
"-D" );
1057 cmd.push_back(
"-X" );
1059 cmd.push_back(
"-p" );
1062 if ( ! oldSolvFile.
empty() )
1063 cmd.push_back( oldSolvFile.
asString() );
1065 cmd.push_back(
"-o" );
1069 std::string errdetail;
1072 WAR <<
" " << output;
1073 if ( errdetail.empty() ) {
1077 errdetail += output;
1080 int ret = prog.
close();
1101 if (
root() ==
"/" )
1112 if ( !
PathInfo(base/
"solv.idx").isExist() )
1115 return build_rpm_solv;
1133 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1134 ", force loading: " << (force?
"true":
"false") << endl;
1139 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1146 if ( newCache || force )
1163 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1169 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1194 if (
PathInfo( historyFile ).isExist() )
1201 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1202 onSystemByAuto.insert( ident );
1224 if (
PathInfo( needrebootFile ).isFile() )
1225 needrebootSpec.
parseFrom( needrebootFile );
1228 if (
PathInfo( needrebootDir ).isDir() )
1233 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1235 if ( ! isRpmConfigBackup( str_r ) )
1237 Pathname needrebootFile { needrebootDir / str_r };
1238 if (
PathInfo( needrebootFile ).isFile() )
1239 needrebootSpec.
parseFrom( needrebootFile );
1250 if ( ! hardLocks.empty() )
1259 createLastDistributionFlavorCache();
1262 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1274 bool explicitDryRun = policy_r.
dryRun();
1284 if (
root() ==
"/" )
1298 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1317 steps.push_back( *it );
1324 MIL <<
"Todo: " << result << endl;
1334 if ( commitPlugins )
1335 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1342 if ( ! policy_r.
dryRun() )
1348 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1355 if ( ! policy_r.
dryRun() )
1377 DBG <<
"dryRun: Not stroring non-package data." << endl;
1384 if ( ! policy_r.
dryRun() )
1386 for_( it, steps.begin(), steps.end() )
1388 if ( ! it->satSolvable().isKind<
Patch>() )
1396 if ( ! patch ||patch->message().empty() )
1399 MIL <<
"Show message for " << patch << endl;
1401 if ( ! report->show( patch ) )
1403 WAR <<
"commit aborted by the user" << endl;
1410 DBG <<
"dryRun: Not checking patch messages." << endl;
1432 for_( it, steps.begin(), steps.end() )
1434 switch ( it->stepType() )
1453 localfile = packageCache.
get( pi );
1456 catch (
const AbortRequestException & exp )
1460 WAR <<
"commit cache preload aborted by the user" << endl;
1464 catch (
const SkipRequestException & exp )
1469 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1479 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1489 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1497 if ( ! policy_r.
dryRun() )
1501 commit( policy_r, packageCache, result );
1505 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1506 if ( explicitDryRun ) {
1516 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1517 if ( explicitDryRun ) {
1529 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1538 if ( commitPlugins )
1539 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1544 if ( ! policy_r.
dryRun() )
1549 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1560 struct NotifyAttemptToModify
1578 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1583 NotifyAttemptToModify attemptToModify( result_r );
1588 AssertProcMounted assertProcMounted(
_root );
1591 std::vector<sat::Solvable> successfullyInstalledPackages;
1594 for_( step, steps.begin(), steps.end() )
1616 localfile = packageCache_r.
get( citem );
1618 catch (
const AbortRequestException &e )
1620 WAR <<
"commit aborted by the user" << endl;
1625 catch (
const SkipRequestException &e )
1628 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1637 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1646 bool success =
false;
1674 WAR <<
"commit aborted by the user" << endl;
1683 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1699 WAR <<
"dry run failed" << endl;
1706 WAR <<
"commit aborted by the user" << endl;
1711 WAR <<
"Install failed" << endl;
1717 if ( success && !policy_r.
dryRun() )
1720 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1729 bool success =
false;
1742 WAR <<
"commit aborted by the user" << endl;
1758 WAR <<
"commit aborted by the user" << endl;
1764 WAR <<
"removal of " << p <<
" failed";
1767 if ( success && !policy_r.
dryRun() )
1774 else if ( ! policy_r.
dryRun() )
1778 if ( ! citem.
buddy() )
1785 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1791 std::string referenceFilename( p->referenceFilename() );
1792 if ( referenceFilename.empty() )
1794 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1798 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1799 if ( !
rpm().hasFile( referencePath.asString() ) )
1804 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1808 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1835 if ( ! successfullyInstalledPackages.empty() )
1838 successfullyInstalledPackages, abort ) )
1840 WAR <<
"Commit aborted by the user" << endl;
1846 successfullyInstalledPackages,
1853 logPatchStatusChanges( result_r.
transaction(), *
this );
1870 namespace zpt = zypp::proto::target;
1873 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1878 NotifyAttemptToModify attemptToModify( result_r );
1884 AssertProcMounted assertProcMounted(
_root );
1899 commit.set_flags( flags );
1907 for (
auto &[key, value] : data ) {
1908 value.resetDispose();
1915 auto &step = steps[stepId];
1932 locCache.value()[stepId] = packageCache_r.
get( citem );
1934 zpt::TransactionStep tStep;
1935 tStep.set_stepid( stepId );
1936 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
1937 tStep.mutable_install()->set_multiversion( p->multiversionInstall() );
1939 *
commit.mutable_steps()->Add( ) = std::move(tStep);
1941 catch (
const AbortRequestException &e )
1943 WAR <<
"commit aborted by the user" << endl;
1948 catch (
const SkipRequestException &e )
1951 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1960 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1966 zpt::TransactionStep tStep;
1967 tStep.set_stepid( stepId );
1968 tStep.mutable_remove()->set_name( p->name() );
1969 tStep.mutable_remove()->set_version( p->edition().version() );
1970 tStep.mutable_remove()->set_release( p->edition().release() );
1971 tStep.mutable_remove()->set_arch( p->arch().asString() );
1973 *
commit.mutable_steps()->Add() = std::move(tStep);
1984 zpt::TransactionStep tStep;
1985 tStep.set_stepid( stepId );
1986 tStep.mutable_install()->set_pathname( locCache.value()[stepId]->asString() );
1987 tStep.mutable_install()->set_multiversion(
false );
1988 *
commit.mutable_steps()->Add() = std::move(tStep);
1992 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1999 std::vector<sat::Solvable> successfullyInstalledPackages;
2001 if (
commit.steps_size() ) {
2004 auto loop = zyppng::EventLoop::create();
2013 int currentStepId = -1;
2019 bool gotEndOfScript =
false;
2022 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2023 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2024 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2025 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2026 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2029 std::optional<zpt::TransactionError> transactionError;
2032 std::string currentScriptType;
2033 std::string currentScriptPackage;
2043 unsigned lineno = 0;
2046 auto msgSource = zyppng::AsyncDataSource::create();
2047 auto scriptSource = zyppng::AsyncDataSource::create();
2052 const auto &sendRpmLineToReport = [&](
const std::string &line ){
2054 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2056 if ( currentStepId >= 0 )
2057 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2058 cmdout.
set(
"line", line );
2059 report->report(cmdout);
2062 if ( installreport ) {
2064 }
else if ( uninstallreport ) {
2066 }
else if ( scriptreport ) {
2068 }
else if ( transactionreport ) {
2070 }
else if ( cleanupreport ) {
2073 WAR <<
"Got rpm output without active report " << line << std::endl;
2078 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2082 if ( line.back() !=
'\n' )
2088 const auto &processDataFromScriptFd = [&](){
2090 while ( scriptSource->canReadLine() ) {
2092 if ( gotEndOfScript )
2095 std::string l = scriptSource->readLine().asString();
2097 DBG <<
"Received end of script tag" << std::endl;
2098 gotEndOfScript =
true;
2099 l = l.substr( 0, l.size() - endOfScriptTag.size() );
2100 if ( l.size() == 0 )
2104 sendRpmLineToReport( l );
2107 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2110 const auto &waitForScriptEnd = [&]() {
2113 if ( gotEndOfScript )
2117 processDataFromScriptFd();
2120 while ( scriptSource->canRead() && !gotEndOfScript ) {
2123 scriptSource->waitForReadyRead( 100 );
2127 const auto &aboutToStartNewReport = [&](){
2129 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2130 ERR <<
"There is still a running report, this is a bug" << std::endl;
2134 DBG <<
"Starting new report, setting gotEndOfScript to false" << std::endl;
2135 gotEndOfScript =
false;
2138 const auto &writeRpmMsgToHistory = [&](){
2139 if ( rpmmsg.size() == 0 )
2143 rpmmsg +=
"[truncated]\n";
2145 std::ostringstream sstr;
2146 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2151 const auto &finalizeCurrentReport = [&]() {
2154 if ( currentStepId >= 0 ) {
2155 step = &steps.at(currentStepId);
2159 if ( installreport ) {
2167 writeRpmMsgToHistory();
2171 ( *installreport)->progress( 100, resObj );
2174 if ( currentStepId >= 0 )
2175 locCache.value().erase( currentStepId );
2176 successfullyInstalledPackages.push_back( step->
satSolvable() );
2182 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2194 writeRpmMsgToHistory();
2197 if ( uninstallreport ) {
2205 writeRpmMsgToHistory();
2209 ( *uninstallreport)->progress( 100, resObj );
2219 writeRpmMsgToHistory();
2222 if ( scriptreport ) {
2224 ( *scriptreport)->progress( 100, resObj );
2227 if ( transactionreport ) {
2229 ( *transactionreport)->progress( 100 );
2232 if ( cleanupreport ) {
2234 ( *cleanupreport)->progress( 100 );
2237 DBG <<
"Report finalized" << std::endl;
2241 currentScriptType.clear();
2242 currentScriptPackage.clear();
2243 installreport.reset();
2244 uninstallreport.reset();
2245 scriptreport.reset();
2246 transactionreport.reset();
2247 cleanupreport.reset();
2257 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2259 const char *argv[] = {
2262 zyppRpmBinary.data(),
2265 auto prog = zyppng::Process::create();
2269 auto messagePipe = zyppng::Pipe::create();
2275 auto scriptPipe = zyppng::Pipe::create();
2279 prog->addFd( messagePipe->writeFd );
2280 prog->addFd( scriptPipe->writeFd );
2283 if ( !scriptSource->open( scriptPipe->readFd ) )
2286 prog->sigStarted().connect( [&](){
2289 messagePipe->unrefWrite();
2290 scriptPipe->unrefWrite();
2293 prog->stdoutDevice()->connectFunc( &zyppng::IODevice::sigReadyRead, [&](){
2294 while( prog->stdoutDevice()->canReadLine() ) {
2295 MIL <<
"zypp-rpm stdout: " << prog->stdoutDevice()->readLine().asStringView() << std::endl;
2300 prog->stderrDevice()->connectFunc( &zyppng::IODevice::sigReadyRead, [&](){
2301 while( prog->stderrDevice()->canReadLine() ) {
2302 MIL <<
"zypp-rpm stderr: " << prog->stderrDevice()->readLine().asStringView() << std::endl;
2308 const auto outFd = prog->stdinFd();
2315 zyppng::rpc::HeaderSizeType msgSize =
commit.ByteSizeLong();
2316 const auto written = zyppng::eintrSafeCall( ::
write, outFd, &msgSize,
sizeof(zyppng::rpc::HeaderSizeType) );
2317 if ( written !=
sizeof(zyppng::rpc::HeaderSizeType) ) {
2318 prog->stop( SIGKILL );
2322 zyppng::FileOutputStream fo ( outFd );
2323 if ( !
commit.SerializeToZeroCopyStream( &fo ) ) {
2324 prog->stop( SIGKILL );
2334 if ( !msgSource->open( messagePipe->readFd ) )
2337 size_t pendingMessageSize = 0;
2338 const auto &processMessages = [&] ( ) {
2342 const auto &parseMsgWithStepId = [&steps](
const auto &m,
auto &p ){
2343 if ( !p.ParseFromString( m.value() ) ) {
2344 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2348 auto id = p.stepid();
2349 if ( id < 0 || id >= steps.size() ) {
2350 ERR <<
"Received invalid stepId: " <<
id <<
" in " << m.messagetypename() <<
" message from zypp-rpm, ignoring." << std::endl;
2356 while ( msgSource->bytesAvailable() ) {
2358 if ( pendingMessageSize == 0 ) {
2359 if ( msgSource->bytesAvailable() >=
sizeof( zyppng::rpc::HeaderSizeType ) ) {
2360 msgSource->read(
reinterpret_cast<char *
>( &pendingMessageSize ),
sizeof( zyppng::rpc::HeaderSizeType ) );
2364 if ( msgSource->bytesAvailable() < pendingMessageSize ) {
2368 auto bytes = msgSource->read( pendingMessageSize );
2369 pendingMessageSize = 0;
2371 zypp::proto::Envelope m;
2372 if (! m.ParseFromArray( bytes.data(), bytes.size() ) ) {
2375 ERR <<
"Received misformed message from zypp-rpm, ignoring" << std::endl;
2383 const auto &mName = m.messagetypename();
2384 if ( mName ==
"zypp.proto.target.RpmLog" ) {
2387 if ( !p.ParseFromString( m.value() ) ) {
2388 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2392 sendRpmLineToReport( p.line() );
2395 }
else if ( mName ==
"zypp.proto.target.PackageBegin" ) {
2396 finalizeCurrentReport();
2398 zpt::PackageBegin p;
2399 if ( !parseMsgWithStepId( m, p ) )
2402 aboutToStartNewReport();
2404 auto & step = steps.at( p.stepid() );
2405 currentStepId = p.stepid();
2407 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2408 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2410 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2411 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2414 }
else if ( mName ==
"zypp.proto.target.PackageFinished" ) {
2415 zpt::PackageFinished p;
2416 if ( !parseMsgWithStepId( m, p ) )
2419 if ( p.stepid() < 0 || p.stepid() > steps.size() )
2426 }
else if ( mName ==
"zypp.proto.target.PackageProgress" ) {
2427 zpt::PackageProgress p;
2428 if ( !parseMsgWithStepId( m, p ) )
2431 if ( uninstallreport )
2432 (*uninstallreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2433 else if ( installreport )
2434 (*installreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2436 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2438 }
else if ( mName ==
"zypp.proto.target.PackageError" ) {
2439 zpt::PackageError p;
2440 if ( !parseMsgWithStepId( m, p ) )
2443 if ( p.stepid() >= 0 && p.stepid() < steps.size() )
2446 finalizeCurrentReport();
2448 }
else if ( mName ==
"zypp.proto.target.ScriptBegin" ) {
2449 finalizeCurrentReport();
2452 if ( !p.ParseFromString( m.value() ) ) {
2453 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2457 aboutToStartNewReport();
2460 const auto stepId = p.stepid();
2461 if ( stepId >= 0 && stepId < steps.size() ) {
2465 currentStepId = p.stepid();
2466 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2467 currentScriptType = p.scripttype();
2468 currentScriptPackage = p.scriptpackage();
2469 (*scriptreport)->start( p.scripttype(), p.scriptpackage(), resPtr );
2471 }
else if ( mName ==
"zypp.proto.target.ScriptFinished" ) {
2474 MIL <<
"Received" << mName <<
" from zypp-rpm" << std::endl;
2476 }
else if ( mName ==
"zypp.proto.target.ScriptError" ) {
2479 if ( !p.ParseFromString( m.value() ) ) {
2480 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2485 const auto stepId = p.stepid();
2486 if ( stepId >= 0 && stepId < steps.size() ) {
2496 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2499 writeRpmMsgToHistory();
2501 if ( !scriptreport ) {
2502 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2511 scriptreport.reset();
2514 }
else if ( mName ==
"zypp.proto.target.CleanupBegin" ) {
2515 finalizeCurrentReport();
2517 zpt::CleanupBegin beg;
2518 if ( !beg.ParseFromString( m.value() ) ) {
2519 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2523 aboutToStartNewReport();
2524 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2525 (*cleanupreport)->start( beg.nvra() );
2526 }
else if ( mName ==
"zypp.proto.target.CleanupFinished" ) {
2528 finalizeCurrentReport();
2530 }
else if ( mName ==
"zypp.proto.target.CleanupProgress" ) {
2531 zpt::CleanupProgress prog;
2532 if ( !prog.ParseFromString( m.value() ) ) {
2533 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2537 if ( !cleanupreport ) {
2538 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2542 (*cleanupreport)->progress( prog.amount() );
2544 }
else if ( mName ==
"zypp.proto.target.TransBegin" ) {
2545 finalizeCurrentReport();
2547 zpt::TransBegin beg;
2548 if ( !beg.ParseFromString( m.value() ) ) {
2549 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2553 aboutToStartNewReport();
2554 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2555 (*transactionreport)->start( beg.name() );
2556 }
else if ( mName ==
"zypp.proto.target.TransFinished" ) {
2558 finalizeCurrentReport();
2560 }
else if ( mName ==
"zypp.proto.target.TransProgress" ) {
2561 zpt::TransProgress prog;
2562 if ( !prog.ParseFromString( m.value() ) ) {
2563 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2567 if ( !transactionreport ) {
2568 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2572 (*transactionreport)->progress( prog.amount() );
2573 }
else if ( mName ==
"zypp.proto.target.TransactionError" ) {
2575 zpt::TransactionError error;
2576 if ( !error.ParseFromString( m.value() ) ) {
2577 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2582 transactionError = std::move(error);
2585 ERR <<
"Received unexpected message from zypp-rpm: "<< m.messagetypename() <<
", ignoring" << std::endl;
2591 msgSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, processMessages );
2594 int zyppRpmExitCode = -1;
2595 prog->connectFunc( &zyppng::Process::sigFinished, [&](
int code ){
2596 zyppRpmExitCode = code;
2600 if ( !prog->start( argv ) ) {
2611 finalizeCurrentReport();
2614 bool readMsgs =
false;
2615 while( prog->stderrDevice()->canReadLine() ) {
2617 MIL <<
"zypp-rpm: " << prog->stderrDevice()->readLine().asStringView();
2619 while( prog->stdoutDevice()->canReadLine() ) {
2621 MIL <<
"zypp-rpm: " << prog->stdoutDevice()->readLine().asStringView();
2624 while ( scriptSource->canReadLine() ) {
2626 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2628 if ( scriptSource->bytesAvailable() > 0 ) {
2630 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2635 switch ( zyppRpmExitCode ) {
2637 case zypprpm::NoError:
2638 case zypprpm::RpmFinishedWithError:
2640 case zypprpm::RpmFinishedWithTransactionError: {
2642 if ( transactionError ) {
2644 std::ostringstream sstr;
2645 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2646 for (
const auto & err : transactionError->problems() ) {
2647 sstr <<
" " << err.message() <<
"\n";
2657 case zypprpm::FailedToOpenDb:
2660 case zypprpm::WrongHeaderSize:
2661 case zypprpm::WrongMessageFormat:
2664 case zypprpm::RpmInitFailed:
2667 case zypprpm::FailedToReadPackage:
2670 case zypprpm::FailedToAddStepToTransaction:
2673 case zypprpm::RpmOrderFailed:
2679 auto &step = steps[stepId];
2691 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2695 std::string referenceFilename( p->referenceFilename() );
2697 if ( referenceFilename.empty() ) {
2698 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2700 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2702 if ( !
rpm().hasFile( referencePath.asString() ) ) {
2706 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2708 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2722 if ( ! successfullyInstalledPackages.empty() )
2725 successfullyInstalledPackages, abort ) )
2727 WAR <<
"Commit aborted by the user" << endl;
2733 successfullyInstalledPackages,
2740 logPatchStatusChanges( result_r.
transaction(), *
this );
2768 if ( baseproduct.isFile() )
2781 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2786 inline Pathname staticGuessRoot(
const Pathname & root_r )
2788 if ( root_r.empty() )
2793 return Pathname(
"/");
2799 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2801 std::ifstream idfile( file_r.c_str() );
2802 for( iostr::EachLine in( idfile ); in; in.next() )
2805 if ( ! line.empty() )
2808 return std::string();
2819 if ( p->isTargetDistribution() )
2827 const Pathname needroot( staticGuessRoot(root_r) );
2828 const Target_constPtr target( getZYpp()->getTarget() );
2829 if ( target && target->root() == needroot )
2830 return target->requestedLocales();
2836 MIL <<
"updateAutoInstalled if changed..." << endl;
2844 {
return baseproductdata(
_root ).registerTarget(); }
2847 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
2850 {
return baseproductdata(
_root ).registerRelease(); }
2853 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
2856 {
return baseproductdata(
_root ).registerFlavor(); }
2859 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
2892 std::string
distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version();
2899 scoped_ptr<rpm::RpmDb> tmprpmdb;
2905 tmprpmdb->initDatabase( );
2921 std::string TargetImpl::distributionFlavor()
const
2923 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
2926 std::string TargetImpl::distributionFlavor(
const Pathname & root_r )
2928 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
2934 std::string guessAnonymousUniqueId(
const Pathname & root_r )
2937 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
2938 if ( ret.
empty() && root_r !=
"/" )
2941 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
2947 std::string TargetImpl::anonymousUniqueId()
const
2949 return guessAnonymousUniqueId(
root() );
2952 std::string TargetImpl::anonymousUniqueId(
const Pathname & root_r )
2954 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
2962 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 it's 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).
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 addIdent(IdString ident_r)
Add all sat::Solvable with this ident_r.
void parseFrom(const InputStream &istr_r)
Parse file istr_r and add it's 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.
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.
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)
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.
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 dirForEach(const Pathname &dir_r, function< bool(const Pathname &, const char *const)> fnc_r)
Invoke callback function fnc_r for each entry in directory dir_r.
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 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()
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
Easy-to use interface to the ZYPP dependency resolver.
std::string asString(const TriBool &val_r, const std::string &istr_r=std::string(), const std::string &tstr_r=std::string(), const std::string &fstr_r=std::string())
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.
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()
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 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.