28#include <zypp-core/base/UserRequestException> 
   64#include <zypp-core/zyppng/base/EventLoop> 
   65#include <zypp-core/zyppng/base/UnixSignalSource> 
   66#include <zypp-core/zyppng/io/AsyncDataSource> 
   67#include <zypp-core/zyppng/io/Process> 
   71#include <zypp-core/zyppng/base/EventDispatcher> 
   73#include <shared/commit/CommitMessages.h> 
   80#include "tools/zypp-rpm/errorcodes.h" 
   81#include <rpm/rpmlog.h> 
   88    static bool val = [](){
 
   89      const char * 
env = getenv(
"TRANSACTIONAL_UPDATE");
 
 
  101#include <solv/repo_rpmdb.h> 
  102#include <solv/chksum.h> 
  112      AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) -> 
void {
 
  113        ::solv_chksum_free( chk, 
nullptr );
 
  115      if ( ::rpm_hash_database_state( state, chk ) == 0 )
 
  118        const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
 
  122        WAR << 
"rpm_hash_database_state failed" << endl;
 
 
  142    inline void sigMultiversionSpecChanged()
 
  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 );
 
 
  232      for ( 
const Transaction::Step & step : steps_r )
 
  234        if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
 
 
 
  249      struct InstallResolvableSAReportReceiver : 
public callback::ReceiveReport<rpm::InstallResolvableReportSA>
 
  251        using ReportType = callback::SendReport<rpm::InstallResolvableReport>;
 
  253        InstallResolvableSAReportReceiver()
 
  254        : _report { 
std::make_unique<ReportType>() }
 
  258        { (*_report)->start( resolvable ); }
 
  261        { (*_report)->progress( value, resolvable ); }
 
  267        std::unique_ptr<ReportType> _report;
 
  270      struct RemoveResolvableSAReportReceiver : 
public callback::ReceiveReport<rpm::RemoveResolvableReportSA>
 
  272        using ReportType = callback::SendReport<rpm::RemoveResolvableReport>;
 
  274        RemoveResolvableSAReportReceiver()
 
  275        : _report { std::make_unique<ReportType>() }
 
  279        { (*_report)->start( resolvable ); }
 
  282        { (*_report)->progress( value, resolvable ); }
 
  288        std::unique_ptr<ReportType> _report;
 
  296      struct SingleTransReportLegacyWrapper
 
  301        SingleTransReportLegacyWrapper()
 
  303          if ( not singleTransReportsConnected() and legacyReportsConnected() )
 
  305            WAR << 
"Activating SingleTransReportLegacyWrapper! The application does not listen to the singletrans reports :(" << endl;
 
  306            _installResolvableSAReportReceiver = InstallResolvableSAReportReceiver();
 
  307            _removeResolvableSAReportReceiver = RemoveResolvableSAReportReceiver();
 
  308            _installResolvableSAReportReceiver->connect();
 
  309            _removeResolvableSAReportReceiver->connect();
 
  314        ~SingleTransReportLegacyWrapper()
 
  318        bool singleTransReportsConnected()
 const 
  329        bool legacyReportsConnected()
 const 
  337        std::optional<InstallResolvableSAReportReceiver> _installResolvableSAReportReceiver;
 
  338        std::optional<RemoveResolvableSAReportReceiver> _removeResolvableSAReportReceiver;
 
  346      class AssertMountedBase
 
  356          if ( ! _mountpoint.empty() ) {
 
  358            MIL << 
"We mounted " << _mountpoint << 
" so we unmount it" << endl;
 
  359            execute({ 
"umount", 
"-R", 
"-l", _mountpoint.asString() });
 
  367          for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
 
  373        Pathname _mountpoint;
 
  379      class AssertProcMounted : 
private AssertMountedBase
 
  382        AssertProcMounted( Pathname root_r )
 
  385          if ( ! PathInfo(root_r/
"self").isDir() ) {
 
  386            MIL << 
"Try to make sure proc is mounted at" << root_r << endl;
 
  388              && execute({ 
"mount", 
"-t", 
"proc", 
"/proc", root_r.asString() }) == 0 ) {
 
  389              _mountpoint = std::move(root_r);  
 
  392              WAR << 
"Mounting proc at " << root_r << 
" failed" << endl;
 
  400      class AssertDevMounted : 
private AssertMountedBase
 
  403        AssertDevMounted( Pathname root_r )
 
  406          if ( ! PathInfo(root_r/
"null").isChr() ) {
 
  407            MIL << 
"Try to make sure dev is mounted at" << root_r << endl;
 
  412              && execute({ 
"mount", 
"--rbind", 
"--make-rslave", 
"/dev", root_r.asString() }) == 0 ) {
 
  413              _mountpoint = std::move(root_r);  
 
  416              WAR << 
"Mounting dev at " << root_r << 
" failed" << endl;
 
  433        std::ifstream infile( historyFile_r.c_str() );
 
  434        for( iostr::EachLine in( infile ); in; in.next() )
 
  436          const char * ch( (*in).c_str() );
 
  438          if ( *ch < 
'1' || 
'9' < *ch )
 
  440          const char * sep1 = ::strchr( ch, 
'|' );      
 
  445          bool installs = 
true;
 
  446          if ( ::strncmp( sep1, 
"install|", 8 ) )
 
  448            if ( ::strncmp( sep1, 
"remove |", 8 ) )
 
  455          const char * sep2 = ::strchr( sep1, 
'|' );    
 
  456          if ( !sep2 || sep1 == sep2 )
 
  458          (*in)[sep2-ch] = 
'\0';
 
  463            onSystemByUserList.erase( pkg );
 
  467          if ( (sep1 = ::strchr( sep2+1, 
'|' ))         
 
  468            && (sep1 = ::strchr( sep1+1, 
'|' ))         
 
  469            && (sep2 = ::strchr( sep1+1, 
'|' )) )       
 
  471            (*in)[sep2-ch] = 
'\0';
 
  472            if ( ::strchr( sep1+1, 
'@' ) )
 
  475              onSystemByUserList.insert( pkg );
 
  480        MIL << 
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
 
  481        return onSystemByUserList;
 
  491        return PluginFrame( command_r, json::Object {
 
  502      MIL << 
"Testcases to keep: " << toKeep << endl;
 
  508        WAR << 
"No Target no Testcase!" << endl;
 
  512      std::string stem( 
"updateTestcase" );
 
  517        std::list<std::string> content;
 
  519        std::set<std::string> cases;
 
  520        for_( c, content.begin(), content.end() )
 
  525        if ( cases.size() >= toKeep )
 
  527          unsigned toDel = cases.size() - toKeep + 1; 
 
  528          for_( c, cases.begin(), cases.end() )
 
  537      MIL << 
"Write new testcase " << next << endl;
 
 
  555      std::pair<bool,PatchScriptReport::Action> doExecuteScript( 
const Pathname & root_r,
 
  565        for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
 
  570            WAR << 
"User request to abort script " << script_r << endl;
 
  579        if ( prog.close() != 0 )
 
  581          ret.second = report_r->problem( prog.execError() );
 
  582          WAR << 
"ACTION" << ret.second << 
"(" << prog.execError() << 
")" << endl;
 
  583          std::ostringstream sstr;
 
  584          sstr << script_r << 
_(
" execution failed") << 
" (" << prog.execError() << 
")" << endl;
 
  585          historylog.
comment(sstr.str(), 
true);
 
  597      bool executeScript( 
const Pathname & root_r,
 
  598                          const Pathname & script_r,
 
  599                          callback::SendReport<PatchScriptReport> & report_r )
 
  604          action = doExecuteScript( root_r, script_r, report_r );
 
  608          switch ( action.second )
 
  611              WAR << 
"User request to abort at script " << script_r << endl;
 
  616              WAR << 
"User request to skip script " << script_r << endl;
 
  626        INT << 
"Abort on unknown ACTION request " << action.second << 
" returned" << endl;
 
  635      bool RunUpdateScripts( 
const Pathname & root_r,
 
  636                             const Pathname & scriptsPath_r,
 
  637                             const std::vector<sat::Solvable> & checkPackages_r,
 
  640        if ( checkPackages_r.empty() )
 
  643        MIL << 
"Looking for new update scripts in (" <<  root_r << 
")" << scriptsPath_r << endl;
 
  645        if ( ! PathInfo( scriptsDir ).isDir() )
 
  648        std::list<std::string> scripts;
 
  650        if ( scripts.empty() )
 
  658        std::map<std::string, Pathname> unify; 
 
  659        for_( it, checkPackages_r.begin(), checkPackages_r.end() )
 
  661          std::string prefix( 
str::form( 
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
 
  662          for_( sit, scripts.begin(), scripts.end() )
 
  667            if ( (*sit)[prefix.size()] != 
'\0' && (*sit)[prefix.size()] != 
'-' )
 
  670            PathInfo script( scriptsDir / *sit );
 
  671            Pathname localPath( scriptsPath_r/(*sit) ); 
 
  672            std::string unifytag;                       
 
  674            if ( script.isFile() )
 
  680            else if ( ! script.isExist() )
 
  688            if ( unifytag.empty() )
 
  692            if ( unify[unifytag].
empty() )
 
  694              unify[unifytag] = localPath;
 
  701              std::string msg( 
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
 
  702              MIL << 
"Skip update script: " << msg << endl;
 
  703              HistoryLog().comment( msg, 
true );
 
  707            if ( abort || aborting_r )
 
  709              WAR << 
"Aborting: Skip update script " << *sit << endl;
 
  710              HistoryLog().comment(
 
  711                  localPath.asString() + 
_(
" execution skipped while aborting"),
 
  716              MIL << 
"Found update script " << *sit << endl;
 
  717              callback::SendReport<PatchScriptReport> report;
 
  720              if ( ! executeScript( root_r, localPath, report ) ) 
 
  732      inline void copyTo( std::ostream & out_r, 
const Pathname & file_r )
 
  734        std::ifstream infile( file_r.c_str() );
 
  735        for( iostr::EachLine in( infile ); in; in.next() )
 
  737          out_r << *in << endl;
 
  741      inline std::string notificationCmdSubst( 
const std::string & cmd_r, 
const UpdateNotificationFile & notification_r )
 
  743        std::string ret( cmd_r );
 
  744#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL ) 
  745        SUBST_IF( 
"%p", notification_r.solvable().asString() );
 
  746        SUBST_IF( 
"%P", notification_r.file().asString() );
 
  751      void sendNotification( 
const Pathname & root_r,
 
  754        if ( notifications_r.empty() )
 
  758        MIL << 
"Notification command is '" << cmdspec << 
"'" << endl;
 
  759        if ( cmdspec.empty() )
 
  762        std::string::size_type pos( cmdspec.find( 
'|' ) );
 
  763        if ( pos == std::string::npos )
 
  765          ERR << 
"Can't send Notification: Missing 'format |' in command spec." << endl;
 
  766          HistoryLog().comment( str::Str() << 
_(
"Error sending update message notification."), 
true );
 
  771        std::string commandStr( 
str::trim( cmdspec.substr( pos + 1 ) ) );
 
  773        enum Format { 
UNKNOWN, NONE, SINGLE, DIGEST, BULK };
 
  775        if ( formatStr == 
"none" )
 
  777        else if ( formatStr == 
"single" )
 
  779        else if ( formatStr == 
"digest" )
 
  781        else if ( formatStr == 
"bulk" )
 
  785          ERR << 
"Can't send Notification: Unknown format '" << formatStr << 
" |' in command spec." << endl;
 
  786          HistoryLog().comment( str::Str() << 
_(
"Error sending update message notification."), 
true );
 
  794        if ( format == NONE || format == SINGLE )
 
  796          for_( it, notifications_r.begin(), notifications_r.end() )
 
  798            std::vector<std::string> command;
 
  799            if ( format == SINGLE )
 
  801            str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
 
  806              for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
 
  810              int ret = prog.close();
 
  813                ERR << 
"Notification command returned with error (" << ret << 
")." << endl;
 
  814                HistoryLog().comment( str::Str() << 
_(
"Error sending update message notification."), 
true );
 
  820        else if ( format == DIGEST || format == BULK )
 
  822          filesystem::TmpFile tmpfile;
 
  823          std::ofstream out( tmpfile.path().c_str() );
 
  824          for_( it, notifications_r.begin(), notifications_r.end() )
 
  826            if ( format == DIGEST )
 
  828              out << it->file() << endl;
 
  830            else if ( format == BULK )
 
  836          std::vector<std::string> command;
 
  837          command.push_back( 
"<"+tmpfile.path().asString() ); 
 
  838          str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
 
  843            for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
 
  847            int ret = prog.close();
 
  850              ERR << 
"Notification command returned with error (" << ret << 
")." << endl;
 
  851              HistoryLog().comment( str::Str() << 
_(
"Error sending update message notification."), 
true );
 
  858          INT << 
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
 
  859          HistoryLog().comment( str::Str() << 
_(
"Error sending update message notification."), 
true );
 
  870      void RunUpdateMessages( 
const Pathname & root_r,
 
  871                              const Pathname & messagesPath_r,
 
  872                              const std::vector<sat::Solvable> & checkPackages_r,
 
  873                              ZYppCommitResult & result_r )
 
  875        if ( checkPackages_r.empty() )
 
  878        MIL << 
"Looking for new update messages in (" <<  root_r << 
")" << messagesPath_r << endl;
 
  880        if ( ! PathInfo( messagesDir ).isDir() )
 
  883        std::list<std::string> messages;
 
  885        if ( messages.empty() )
 
  891        HistoryLog historylog;
 
  892        for_( it, checkPackages_r.begin(), checkPackages_r.end() )
 
  894          std::string prefix( 
str::form( 
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
 
  895          for_( sit, messages.begin(), messages.end() )
 
  900            if ( (*sit)[prefix.size()] != 
'\0' && (*sit)[prefix.size()] != 
'-' )
 
  903            PathInfo message( messagesDir / *sit );
 
  904            if ( ! message.isFile() || message.size() == 0 )
 
  907            MIL << 
"Found update message " << *sit << endl;
 
  908            Pathname localPath( messagesPath_r/(*sit) ); 
 
  909            result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
 
  910            historylog.comment( str::Str() << 
_(
"New update message") << 
" " << localPath, 
true );
 
  913        sendNotification( root_r, result_r.updateMessages() );
 
  919      void logPatchStatusChanges( 
const sat::Transaction & transaction_r, 
TargetImpl & target_r )
 
  922        if ( changedPseudoInstalled.empty() )
 
  930          WAR << 
"Need to recompute the patch status changes as commit is incomplete!" << endl;
 
  933          changedPseudoInstalled = establishedStates.changedPseudoInstalled();
 
  936        HistoryLog historylog;
 
  937        for ( 
const auto & el : changedPseudoInstalled )
 
  938          historylog.patchStateChange( el.first, el.second );
 
  947                             const std::vector<sat::Solvable> & checkPackages_r,
 
  949    { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
 
 
  967      _rpm.initDatabase( root_r, doRebuild_r );
 
  972      sigMultiversionSpecChanged();     
 
  973      MIL << 
"Initialized target on " << 
_root << endl;
 
 
  981      std::ifstream uuidprovider( 
"/proc/sys/kernel/random/uuid" );
 
 
  991                            boost::function<
bool ()> condition,
 
  992                            boost::function<std::string ()> value )
 
  994        std::string val = value();
 
 1002            MIL << 
"updating '" << filename << 
"' content." << endl;
 
 1006            std::ofstream filestr;
 
 1009            filestr.open( filename.
c_str() );
 
 1011            if ( filestr.good() )
 
 
 1033      if ( 
root() != 
"/" )
 
 1047        WAR << 
"Can't create anonymous id file" << endl;
 
 
 1056      Pathname flavorpath( 
home() / 
"LastDistributionFlavor");
 
 1062          WAR << 
"No base product, I won't create flavor cache" << endl;
 
 1066      std::string flavor = p->flavor();
 
 1078        WAR << 
"Can't create flavor cache" << endl;
 
 
 1090      _rpm.closeDatabase();
 
 1091      sigMultiversionSpecChanged();     
 
 1092      MIL << 
"Closed target on " << 
_root << endl;
 
 
 1118      bool build_rpm_solv = 
true;
 
 1128        MIL << 
"Read cookie: " << cookie << endl;
 
 1133          if ( status == rpmstatus )
 
 1134            build_rpm_solv = 
false;
 
 1135          MIL << 
"Read cookie: " << rpmsolvcookie << 
" says: " 
 1136          << (build_rpm_solv ? 
"outdated" : 
"uptodate") << endl;
 
 1140      if ( build_rpm_solv )
 
 1154          bool switchingToTmpSolvfile = 
false;
 
 1155          Exception ex(
"Failed to cache rpm database.");
 
 1161            rpmsolv       = 
base/
"solv";
 
 1162            rpmsolvcookie = 
base/
"cookie";
 
 1169              WAR << 
"Using a temporary solv file at " << 
base << endl;
 
 1170              switchingToTmpSolvfile = 
true;
 
 1179          if ( ! switchingToTmpSolvfile )
 
 1189#ifdef ZYPP_RPMDB2SOLV_PATH 
 1190        cmd.push_back( ZYPP_RPMDB2SOLV_PATH );
 
 1192        cmd.push_back( 
"rpmdb2solv" );
 
 1194        if ( ! 
_root.empty() ) {
 
 1195          cmd.push_back( 
"-r" );
 
 1196          cmd.push_back( 
_root.asString() );
 
 1198        cmd.push_back( 
"-D" );
 
 1200        cmd.push_back( 
"-X" );  
 
 1202        cmd.push_back( 
"-p" );
 
 1205        if ( ! oldSolvFile.
empty() )
 
 1206          cmd.push_back( oldSolvFile.
asString() );
 
 1208        cmd.push_back( 
"-o" );
 
 1212        std::string errdetail;
 
 1215          WAR << 
"  " << output;
 
 1216          if ( errdetail.empty() ) {
 
 1220          errdetail += output;
 
 1223        int ret = prog.
close();
 
 1244        if ( 
root() == 
"/" )
 
 1258      return build_rpm_solv;
 
 
 1276      MIL << 
"New cache built: " << (newCache?
"true":
"false") <<
 
 1277        ", force loading: " << (force?
"true":
"false") << endl;
 
 1282      MIL << 
"adding " << rpmsolv << 
" to pool(" << satpool.
systemRepoAlias() << 
")" << endl;
 
 1289        if ( newCache || force )
 
 1306        MIL << 
"adding " << rpmsolv << 
" to system" << endl;
 
 1312        MIL << 
"Try to handle exception by rebuilding the solv-file" << endl;
 
 1337          if ( 
PathInfo( historyFile ).isExist() )
 
 1344              if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
 
 1345                onSystemByAuto.insert( ident );
 
 1361        sat::SolvableSpec needrebootSpec;
 
 1362        needrebootSpec.addProvides( 
Capability(
"installhint(reboot-needed)") );
 
 1363        needrebootSpec.addProvides( 
Capability(
"kernel") );
 
 1366        if ( 
PathInfo( needrebootFile ).isFile() )
 
 1367          needrebootSpec.parseFrom( needrebootFile );
 
 1370        if ( 
PathInfo( needrebootDir ).isDir() )
 
 1375                                  [&]( 
const Pathname & dir_r, 
const char *
const str_r )->
bool 
 1377                                    if ( ! isRpmConfigBackup( str_r ) )
 
 1379                                      Pathname needrebootFile { needrebootDir / str_r };
 
 1380                                      if ( 
PathInfo( needrebootFile ).isFile() )
 
 1381                                        needrebootSpec.parseFrom( needrebootFile );
 
 1392        if ( ! hardLocks.empty() )
 
 1401      MIL << 
"Target loaded: " << system.
solvablesSize() << 
" resolvables" << endl;
 
 
 1413      bool explicitDryRun = policy_r.
dryRun();    
 
 1423        if ( 
root() == 
"/" )
 
 1437      MIL << 
"TargetImpl::commit(<pool>, " << policy_r << 
")" << endl;
 
 1456          steps.push_back( *it );
 
 1463      MIL << 
"Todo: " << result << endl;
 
 1474      if ( commitPlugins )
 
 1475        commitPlugins.
send( transactionPluginFrame( 
"COMMITBEGIN", steps ) );
 
 1482        if ( ! policy_r.
dryRun() )
 
 1488          DBG << 
"dryRun: Not writing upgrade testcase." << endl;
 
 1495      if ( ! policy_r.
dryRun() )
 
 1517        DBG << 
"dryRun: Not storing non-package data." << endl;
 
 1524      if ( ! policy_r.
dryRun() )
 
 1526        for_( it, steps.begin(), steps.end() )
 
 1528          if ( ! it->satSolvable().isKind<
Patch>() )
 
 1536          if ( ! patch ||patch->message().empty()  )
 
 1539          MIL << 
"Show message for " << patch << endl;
 
 1541          if ( ! report->show( patch ) )
 
 1543            WAR << 
"commit aborted by the user" << endl;
 
 1550        DBG << 
"dryRun: Not checking patch messages." << endl;
 
 1565        std::unique_ptr<CommitPackagePreloader> preloader;
 
 1571            preloader = std::make_unique<CommitPackagePreloader>();
 
 1572            preloader->preloadTransaction( steps );
 
 1573            miss = preloader->missed ();
 
 1580            for_( it, steps.begin(), steps.end() )
 
 1582              switch ( it->stepType() )
 
 1601                  localfile = packageCache.
get( pi );
 
 1604                catch ( 
const AbortRequestException & exp )
 
 1608                  WAR << 
"commit cache preload aborted by the user" << endl;
 
 1612                catch ( 
const SkipRequestException & exp )
 
 1617                  WAR << 
"Skipping cache preload package " << pi->asKind<
Package>() << 
" in commit" << endl;
 
 1627                  INT << 
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() << 
" in commit" << endl;
 
 1638          ERR << 
"Some packages could not be provided. Aborting commit."<< endl;
 
 1642          if ( ! policy_r.
dryRun() )
 
 1650              commit( policy_r, packageCache, result );
 
 1654              preloader->cleanupCaches ();
 
 1658            DBG << 
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
 
 1659            if ( explicitDryRun ) {
 
 1673        DBG << 
"dryRun: Not downloading/installing/deleting anything." << endl;
 
 1674        if ( explicitDryRun ) {
 
 1686          WAR << 
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
 
 1695      if ( commitPlugins )
 
 1696        commitPlugins.
send( transactionPluginFrame( 
"COMMITEND", steps ) );
 
 1701      if ( ! policy_r.
dryRun() )
 
 1706      MIL << 
"TargetImpl::commit(<pool>, " << policy_r << 
") returns: " << result << endl;
 
 
 1717      struct NotifyAttemptToModify
 
 1719        NotifyAttemptToModify( 
ZYppCommitResult & result_r ) : _result( result_r ) {}
 
 1722        { 
if ( _guard ) { _result.attemptToModify( 
true ); _guard = 
false; } }
 
 1725        ZYppCommitResult & _result;
 
 1734        { 
"ZYPP_SINGLE_RPMTRANS", 
nullptr },
 
 1735        { 
"ZYPP_CLASSIC_RPMTRANS", 
"1" },
 
 1740      MIL << 
"TargetImpl::commit(<list>" << policy_r << 
")" << steps.size() << endl;
 
 1745      NotifyAttemptToModify attemptToModify( result_r );
 
 1750      AssertProcMounted assertProcMounted( 
_root );
 
 1751      AssertDevMounted assertDevMounted( 
_root ); 
 
 1758      std::vector<sat::Solvable> successfullyInstalledPackages;
 
 1761      for_( step, steps.begin(), steps.end() )
 
 1766          if ( citem->isKind<
Package>() )
 
 1770            obsoletedPackages.insert( citem->ident() );
 
 1776        if ( citem->isKind<
Package>() )
 
 1784              localfile = packageCache_r.
get( citem );
 
 1786            catch ( 
const AbortRequestException &e )
 
 1788              WAR << 
"commit aborted by the user" << endl;
 
 1793            catch ( 
const SkipRequestException &e )
 
 1796              WAR << 
"Skipping package " << p << 
" in commit" << endl;
 
 1805              INT << 
"Unexpected Error: Skipping package " << p << 
" in commit" << endl;
 
 1814            bool success = 
false;
 
 1840                WAR << 
"commit aborted by the user" << endl;
 
 1849                  auto rebootNeededFile = 
root() / 
"/run/reboot-needed";
 
 1865                WAR << 
"dry run failed" << endl;
 
 1872                WAR << 
"commit aborted by the user" << endl;
 
 1877                WAR << 
"Install failed" << endl;
 
 1883            if ( success && !policy_r.
dryRun() )
 
 1886              successfullyInstalledPackages.push_back( citem.
satSolvable() );
 
 1895            bool success = 
false;
 
 1908                WAR << 
"commit aborted by the user" << endl;
 
 1924                WAR << 
"commit aborted by the user" << endl;
 
 1930              WAR << 
"removal of " << p << 
" failed";
 
 1933            if ( success && !policy_r.
dryRun() )
 
 1940        else if ( ! policy_r.
dryRun() ) 
 
 1944          if ( ! citem.
buddy() )
 
 1946            if ( citem->isKind<
Product>() )
 
 1951                ERR << 
"Can't install orphan product without release-package! " << citem << endl;
 
 1957                std::string referenceFilename( p->referenceFilename() );
 
 1958                if ( referenceFilename.empty() )
 
 1960                  ERR << 
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
 
 1964                  Pathname referencePath { 
Pathname(
"/etc/products.d") / referenceFilename };   
 
 1965                  if ( ! 
rpm().hasFile( referencePath.
asString() ) )
 
 1970                      ERR << 
"Delete orphan product failed: " << referencePath << endl;
 
 1974                    WAR << 
"Won't remove orphan product: '/etc/products.d/" << referenceFilename << 
"' is owned by a package." << endl;
 
 2003      if ( ! successfullyInstalledPackages.empty() )
 
 2006                                 successfullyInstalledPackages, abort ) )
 
 2008          WAR << 
"Commit aborted by the user" << endl;
 
 2014                           successfullyInstalledPackages,
 
 2021      logPatchStatusChanges( result_r.
transaction(), *
this );
 
 
 2040      void sendLogline( 
const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
 
 2043        data.
set( 
"line", std::cref(line_r) );
 
 2044        data.
set( 
"level", level_r );
 
 
 2050        auto u2rpmlevel = []( 
unsigned rpmlevel_r ) -> ReportType::loglevel {
 
 2051          switch ( rpmlevel_r ) {
 
 2052            case RPMLOG_EMERG:  [[fallthrough]];  
 
 2053            case RPMLOG_ALERT:  [[fallthrough]];  
 
 2055              return ReportType::loglevel::crt;
 
 2057              return ReportType::loglevel::err;
 
 2058            case RPMLOG_WARNING:                  
 
 2059              return ReportType::loglevel::war;
 
 2060            default:            [[fallthrough]];
 
 2061            case RPMLOG_NOTICE: [[fallthrough]];  
 
 2063              return ReportType::loglevel::msg;
 
 2065              return ReportType::loglevel::dbg;
 
 
 2073      { (*this)->report( userData_r ); }
 
 
 
 2079        { 
"ZYPP_SINGLE_RPMTRANS", 
"1" },
 
 2080        { 
"ZYPP_CLASSIC_RPMTRANS", 
nullptr },
 
 2083      SingleTransReportLegacyWrapper _legacyWrapper;  
 
 2088      MIL << 
"TargetImpl::commit(<list>" << policy_r << 
")" << steps.size() << endl;
 
 2093      NotifyAttemptToModify attemptToModify( result_r );
 
 2099      AssertProcMounted assertProcMounted( 
_root );
 
 2100      AssertDevMounted assertDevMounted( 
_root ); 
 
 2114      proto::target::Commit 
commit;
 
 2124        for ( 
auto &[
_, value] : data ) {
 
 2126          value.resetDispose();
 
 2132      for ( 
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
 
 2133        auto &step = steps[stepId];
 
 2136          if ( citem->isKind<
Package>() )
 
 2145        if ( citem->isKind<
Package>() ) {
 
 2150              locCache.value()[stepId] = packageCache_r.
get( citem );
 
 2152              proto::target::InstallStep tStep;
 
 2153              tStep.stepId        = stepId;
 
 2154              tStep.pathname      = locCache.
value()[stepId]->asString();
 
 2155              tStep.multiversion  = p->multiversionInstall() ;
 
 2157              commit.transactionSteps.push_back( std::move(tStep) );
 
 2159            catch ( 
const AbortRequestException &e )
 
 2161              WAR << 
"commit aborted by the user" << endl;
 
 2166            catch ( 
const SkipRequestException &e )
 
 2169              WAR << 
"Skipping package " << p << 
" in commit" << endl;
 
 2178              INT << 
"Unexpected Error: Skipping package " << p << 
" in commit" << endl;
 
 2184            proto::target::RemoveStep tStep;
 
 2185            tStep.stepId  = stepId;
 
 2186            tStep.name    = p->name();
 
 2187            tStep.version = p->edition().version();
 
 2188            tStep.release = p->edition().release();
 
 2189            tStep.arch    = p->arch().asString();
 
 2190            commit.transactionSteps.push_back(std::move(tStep));
 
 2201            proto::target::InstallStep tStep;
 
 2202            tStep.stepId        = stepId;
 
 2203            tStep.pathname      = locCache.value()[stepId]->asString();
 
 2204            tStep.multiversion  = 
false;
 
 2205            commit.transactionSteps.push_back(std::move(tStep));
 
 2209            INT << 
"Unexpected Error: Skipping package " << p << 
" in commit" << endl;
 
 2216      std::vector<sat::Solvable> successfullyInstalledPackages;
 
 2218      if ( 
commit.transactionSteps.size() ) {
 
 2225        const std::vector<int> interceptedSignals {
 
 2232        auto unixSignals = loop->eventDispatcher()->unixSignalSource();
 
 2233        unixSignals->sigReceived ().connect ([]( 
int signum ){
 
 2235          JobReport::error ( 
str::Format(
_(
"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it is not possible to cancel a running rpm transaction.") ) % strsignal(signum) % signum );
 
 2237        for( 
const auto &sig : interceptedSignals )
 
 2238          unixSignals->addSignal ( sig );
 
 2241          for( 
const auto &sig : interceptedSignals )
 
 2242            unixSignals->removeSignal ( sig );
 
 2249        int currentStepId = -1;
 
 2255        bool gotEndOfScript = 
false;
 
 2258        std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>>        transactionreport;
 
 2259        std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>>  installreport;
 
 2260        std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>>   uninstallreport;
 
 2261        std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>>       scriptreport;
 
 2262        std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>>     cleanupreport;
 
 2265        std::optional<proto::target::TransactionError> transactionError;
 
 2268        std::string currentScriptType;
 
 2269        std::string currentScriptPackage;
 
 2279        unsigned    lineno = 0;
 
 2287        zyppng::StompFrameStreamRef msgStream;
 
 2292        const auto &sendRpmLineToReport = [&]( 
const std::string &line ){
 
 2294          const auto &sendLogRep = [&]( 
auto &report, 
const auto &cType ){
 
 2296            if ( currentStepId >= 0 )
 
 2297              cmdout.
set( 
"solvable", steps.at(currentStepId).satSolvable() );
 
 2298            cmdout.
set( 
"line", line );
 
 2302          if ( installreport ) {
 
 2303            sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout );
 
 2304          } 
else if ( uninstallreport ) {
 
 2305            sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout );
 
 2306          } 
else if ( scriptreport ) {
 
 2307            sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout );
 
 2308          } 
else if ( transactionreport ) {
 
 2309            sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout );
 
 2310          } 
else if ( cleanupreport ) {
 
 2311            sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout );
 
 2313            WAR << 
"Got rpm output without active report " << line; 
 
 2318            if ( line.find( 
" scriptlet failed, " ) == std::string::npos )      
 
 2322          if ( line.back() != 
'\n' )
 
 2328        const auto &processDataFromScriptFd = [&](){
 
 2330          while ( scriptSource->canReadLine() ) {
 
 2332            if ( gotEndOfScript )
 
 2335            std::string l = scriptSource->readLine().asString();
 
 2337              gotEndOfScript = 
true;
 
 2338              std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
 
 2341              l = l.substr( 0, rawsize );
 
 2343            L_DBG(
"zypp-rpm") << 
"[rpm> " << l; 
 
 2344            sendRpmLineToReport( l );
 
 2347        scriptSource->sigReadyRead().connect( processDataFromScriptFd );
 
 2350        const auto &waitForScriptEnd = [&]() {
 
 2353          if ( gotEndOfScript )
 
 2357          processDataFromScriptFd();
 
 2360          while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
 
 2363            scriptSource->waitForReadyRead( 100 );
 
 2367        const auto &aboutToStartNewReport = [&](){
 
 2369          if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
 
 2370            ERR << 
"There is still a running report, this is a bug" << std::endl;
 
 2374          gotEndOfScript = 
false;
 
 2377        const auto &writeRpmMsgToHistory = [&](){
 
 2378          if ( rpmmsg.size() == 0 )
 
 2382            rpmmsg += 
"[truncated]\n";
 
 2384          std::ostringstream sstr;
 
 2385          sstr << 
"rpm output:" << endl << rpmmsg << endl;
 
 2390        const auto &finalizeCurrentReport = [&]() {
 
 2393          if ( currentStepId >= 0 ) {
 
 2394            step = &steps.at(currentStepId);
 
 2398          if ( installreport ) {
 
 2406              writeRpmMsgToHistory();
 
 2410              ( *installreport)->progress( 100, resObj );
 
 2413              if ( currentStepId >= 0 )
 
 2414                locCache.value().erase( currentStepId );
 
 2415              successfullyInstalledPackages.push_back( step->
satSolvable() );
 
 2421                  auto rebootNeededFile = 
root() / 
"/run/reboot-needed";
 
 2433              writeRpmMsgToHistory();
 
 2436          if ( uninstallreport ) {
 
 2444              writeRpmMsgToHistory();
 
 2448              ( *uninstallreport)->progress( 100, resObj );
 
 2458              writeRpmMsgToHistory();
 
 2461          if ( scriptreport ) {
 
 2463            ( *scriptreport)->progress( 100, resObj );
 
 2466          if ( transactionreport ) {
 
 2468            ( *transactionreport)->progress( 100 );
 
 2471          if ( cleanupreport ) {
 
 2473            ( *cleanupreport)->progress( 100 );
 
 2479          currentScriptType.clear();
 
 2480          currentScriptPackage.clear();
 
 2481          installreport.reset();
 
 2482          uninstallreport.reset();
 
 2483          scriptreport.reset();
 
 2484          transactionreport.reset();
 
 2485          cleanupreport.reset();
 
 2495        constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
 
 2497        const char *argv[] = {
 
 2500          zyppRpmBinary.data(),
 
 2517        prog->addFd( messagePipe->writeFd );
 
 2518        prog->addFd( scriptPipe->writeFd );
 
 2521        if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
 
 2524        const auto &processMessages = [&] ( ) {
 
 2528          const auto &checkMsgWithStepId = [&steps]( 
auto &p ){
 
 2530              ERR << 
"Failed to parse message from zypp-rpm." << std::endl;
 
 2534            auto id = p->stepId;
 
 2535            if ( id < 0 || id >= steps.size() ) {
 
 2536              ERR << 
"Received invalid stepId: " << 
id << 
" in " << p->typeName << 
" message from zypp-rpm, ignoring." << std::endl;
 
 2542          while ( 
const auto &m = msgStream->nextMessage() ) {
 
 2548            const auto &mName = m->command();
 
 2549            if (  mName == proto::target::RpmLog::typeName )  {
 
 2551              const auto &p = proto::target::RpmLog::fromStompMessage (*m);
 
 2553                ERR << 
"Failed to parse " << proto::target::RpmLog::typeName << 
" message from zypp-rpm." << std::endl;
 
 2556              ( p->level >= RPMLOG_ERR     ? 
L_ERR(
"zypp-rpm")
 
 2557              : p->level >= RPMLOG_WARNING ? 
L_WAR(
"zypp-rpm")
 
 2558              : 
L_DBG(
"zypp-rpm") ) << 
"[rpm " << p->level << 
"> " << p->line; 
 
 2561            } 
else if (  mName == proto::target::PackageBegin::typeName )  {
 
 2562              finalizeCurrentReport();
 
 2564              const auto &p = proto::target::PackageBegin::fromStompMessage(*m);
 
 2565              if ( !checkMsgWithStepId( p ) )
 
 2568              aboutToStartNewReport();
 
 2570              auto & step = steps.at( p->stepId );
 
 2571              currentStepId = p->stepId;
 
 2573                uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
 
 2574                ( *uninstallreport )->start( 
makeResObject( step.satSolvable() ) );
 
 2576                installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
 
 2577                ( *installreport )->start( 
makeResObject( step.satSolvable() ) );
 
 2580            } 
else if (  mName == proto::target::PackageFinished::typeName )  {
 
 2581              const auto &p = proto::target::PackageFinished::fromStompMessage(*m);
 
 2582              if ( !checkMsgWithStepId( p ) )
 
 2589            } 
else if (  mName == proto::target::PackageProgress::typeName )  {
 
 2590              const auto &p = proto::target::PackageProgress::fromStompMessage(*m);
 
 2591              if ( !checkMsgWithStepId( p ) )
 
 2594              if ( uninstallreport )
 
 2595                (*uninstallreport)->progress( p->amount, 
makeResObject( steps.at( p->stepId ) ));
 
 2596              else if ( installreport )
 
 2597                (*installreport)->progress( p->amount, 
makeResObject( steps.at( p->stepId ) ));
 
 2599                ERR << 
"Received a " << mName << 
" message but there is no corresponding report running." << std::endl;
 
 2601            } 
else if (  mName == proto::target::PackageError::typeName )  {
 
 2602              const auto &p = proto::target::PackageError::fromStompMessage(*m);
 
 2603              if ( !checkMsgWithStepId( p ) )
 
 2606              if ( p->stepId >= 0 && p->stepId < steps.size() )
 
 2609              finalizeCurrentReport();
 
 2611            } 
else if (  mName == proto::target::ScriptBegin::typeName )  {
 
 2612              finalizeCurrentReport();
 
 2614              const auto &p = proto::target::ScriptBegin::fromStompMessage(*m);
 
 2616                ERR << 
"Failed to parse " << proto::target::ScriptBegin::typeName << 
" message from zypp-rpm." << std::endl;
 
 2620              aboutToStartNewReport();
 
 2623              const auto stepId = p->stepId;
 
 2624              if ( stepId >= 0 && 
static_cast<size_t>(stepId) < steps.size() ) {
 
 2628              currentStepId = p->stepId;
 
 2629              scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
 
 2630              currentScriptType = p->scriptType;
 
 2631              currentScriptPackage = p->scriptPackage;
 
 2632              (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr );
 
 2634            } 
else if (  mName == proto::target::ScriptFinished::typeName )  {
 
 2638            } 
else if (  mName == proto::target::ScriptError::typeName )  {
 
 2640              const auto &p = proto::target::ScriptError::fromStompMessage(*m);
 
 2642                ERR << 
"Failed to parse " << proto::target::ScriptError::typeName << 
" message from zypp-rpm." << std::endl;
 
 2647              const auto stepId = p->stepId;
 
 2648              if ( stepId >= 0 && 
static_cast<size_t>(stepId) < steps.size() ) {
 
 2658                str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() : 
"unknown" ),
 
 2661              writeRpmMsgToHistory();
 
 2663              if ( !scriptreport ) {
 
 2664                ERR << 
"Received a ScriptError message, but there is no running report. " << std::endl;
 
 2673              scriptreport.reset();
 
 2676            } 
else if (  mName == proto::target::CleanupBegin::typeName ) {
 
 2677              finalizeCurrentReport();
 
 2679              const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m);
 
 2681                ERR << 
"Failed to parse " << proto::target::CleanupBegin::typeName << 
" message from zypp-rpm." << std::endl;
 
 2685              aboutToStartNewReport();
 
 2686              cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
 
 2687              (*cleanupreport)->start( beg->nvra );
 
 2688            } 
else if (  mName == proto::target::CleanupFinished::typeName )  {
 
 2690              finalizeCurrentReport();
 
 2692            } 
else if (  mName == proto::target::CleanupProgress::typeName )  {
 
 2693              const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m);
 
 2695                ERR << 
"Failed to parse " << proto::target::CleanupProgress::typeName << 
" message from zypp-rpm." << std::endl;
 
 2699              if ( !cleanupreport ) {
 
 2700                ERR << 
"Received a CleanupProgress message, but there is no running report. " << std::endl;
 
 2704              (*cleanupreport)->progress( prog->amount );
 
 2706            } 
else if (  mName == proto::target::TransBegin::typeName ) {
 
 2707              finalizeCurrentReport();
 
 2709              const auto &beg = proto::target::TransBegin::fromStompMessage(*m);
 
 2711                ERR << 
"Failed to parse " << proto::target::TransBegin::typeName << 
" message from zypp-rpm." << std::endl;
 
 2715              aboutToStartNewReport();
 
 2716              transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
 
 2717              (*transactionreport)->start( beg->name );
 
 2718            } 
else if (  mName == proto::target::TransFinished::typeName )  {
 
 2720              finalizeCurrentReport();
 
 2722            } 
else if (  mName == proto::target::TransProgress::typeName )  {
 
 2723              const auto &prog = proto::target::TransProgress::fromStompMessage(*m);
 
 2725                ERR << 
"Failed to parse " << proto::target::TransProgress::typeName << 
" message from zypp-rpm." << std::endl;
 
 2729              if ( !transactionreport ) {
 
 2730                ERR << 
"Received a TransactionProgress message, but there is no running report. " << std::endl;
 
 2734              (*transactionreport)->progress( prog->amount );
 
 2735            } 
else if ( mName == proto::target::TransactionError::typeName ) {
 
 2737              const auto &error = proto::target::TransactionError::fromStompMessage(*m);
 
 2739                ERR << 
"Failed to parse " << proto::target::TransactionError::typeName  << 
" message from zypp-rpm." << std::endl;
 
 2744              transactionError = std::move(*error);
 
 2747              ERR << 
"Received unexpected message from zypp-rpm: "<< m->command() << 
", ignoring" << std::endl;
 
 2755        prog->sigStarted().connect( [&](){
 
 2758          messagePipe->unrefWrite();
 
 2759          scriptPipe->unrefWrite();
 
 2763            while( prog->canReadLine( channel ) ) {
 
 2764              L_ERR(
"zypp-rpm") <<  ( channel == 
zyppng::Process::StdOut ? 
"<stdout> " : 
"<stderr> " ) << prog->channelReadLine( channel ).asStringView();  
 
 2770          if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd }, prog->stdinFd() ) )
 
 2776          const auto &msg = 
commit.toStompMessage();
 
 2778            std::rethrow_exception ( msg.error() );
 
 2780          if ( !msgStream->sendMessage( *msg ) ) {
 
 2781            prog->stop( SIGKILL );
 
 2787        int zyppRpmExitCode = -1;
 
 2789          zyppRpmExitCode = code;
 
 2793        if ( !prog->start( argv ) ) {
 
 2802          msgStream->readAllMessages();
 
 2809        finalizeCurrentReport();
 
 2812        bool readMsgs = 
false;
 
 2822        while ( scriptSource->canReadLine() ) {
 
 2824          MIL << 
"rpm-script-fd: " << scriptSource->readLine().asStringView();
 
 2826        if ( scriptSource->bytesAvailable() > 0 ) {
 
 2828          MIL << 
"rpm-script-fd: " << scriptSource->readAll().asStringView();
 
 2833        switch ( zyppRpmExitCode ) {
 
 2835          case zypprpm::NoError:
 
 2836          case zypprpm::RpmFinishedWithError:
 
 2838          case zypprpm::RpmFinishedWithTransactionError: {
 
 2840            if ( transactionError ) {
 
 2842              std::ostringstream sstr;
 
 2843              sstr << 
_(
"Executing the transaction failed because of the following problems:") << 
"\n";
 
 2844              for ( 
const auto & err : transactionError->problems ) {
 
 2845                sstr << 
"    " << err << 
"\n";
 
 2855          case zypprpm::FailedToOpenDb:
 
 2858          case zypprpm::WrongHeaderSize:
 
 2859          case zypprpm::WrongMessageFormat:
 
 2862          case zypprpm::RpmInitFailed:
 
 2865          case zypprpm::FailedToReadPackage:
 
 2868          case zypprpm::FailedToAddStepToTransaction:
 
 2871          case zypprpm::RpmOrderFailed:
 
 2874          case zypprpm::FailedToCreateLock:
 
 2879        for ( 
int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
 
 2880          auto &step = steps[stepId];
 
 2892                  ERR << 
"Can't install orphan product without release-package! " << citem << endl;
 
 2896                  std::string referenceFilename( p->referenceFilename() );
 
 2898                  if ( referenceFilename.empty() ) {
 
 2899                    ERR << 
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
 
 2901                    Pathname referencePath { 
Pathname(
"/etc/products.d") / referenceFilename }; 
 
 2903                    if ( ! 
rpm().hasFile( referencePath.
asString() ) ) {
 
 2907                        ERR << 
"Delete orphan product failed: " << referencePath << endl;
 
 2909                      WAR << 
"Won't remove orphan product: '/etc/products.d/" << referenceFilename << 
"' is owned by a package." << endl;
 
 2923      if ( ! successfullyInstalledPackages.empty() )
 
 2926               successfullyInstalledPackages, abort ) )
 
 2928          WAR << 
"Commit aborted by the user" << endl;
 
 2934          successfullyInstalledPackages,
 
 2941      logPatchStatusChanges( result_r.
transaction(), *
this );
 
 
 2958      return _rpm.hasFile(path_str, name_str);
 
 
 2969        if ( baseproduct.isFile() )
 
 2982          ERR << 
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
 
 2987      inline Pathname staticGuessRoot( 
const Pathname & root_r )
 
 2989        if ( root_r.empty() )
 
 2994            return Pathname(
"/");
 
 3000      inline std::string firstNonEmptyLineIn( 
const Pathname & file_r )
 
 3002        std::ifstream idfile( file_r.c_str() );
 
 3003        for( iostr::EachLine in( idfile ); in; in.next() )
 
 3006          if ( ! line.empty() )
 
 3009        return std::string();
 
 3020        if ( p->isTargetDistribution() )
 
 
 3028      const Pathname needroot( staticGuessRoot(root_r) );
 
 3031        return target->requestedLocales();
 
 
 3037      MIL << 
"updateAutoInstalled if changed..." << endl;
 
 
 3045    { 
return baseproductdata( 
_root ).registerTarget(); }
 
 
 3048    { 
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
 
 
 3051    { 
return baseproductdata( 
_root ).registerRelease(); }
 
 
 3054    { 
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
 
 
 3057    { 
return baseproductdata( 
_root ).registerFlavor(); }
 
 
 3060    { 
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
 
 
 3093      const Pathname & needroot = staticGuessRoot(root_r);
 
 
 3111      return firstNonEmptyLineIn( 
home() / 
"LastDistributionFlavor" );
 
 
 3116      return firstNonEmptyLineIn( staticGuessRoot(root_r) / 
"/var/lib/zypp/LastDistributionFlavor" );
 
 
 3122      std::string guessAnonymousUniqueId( 
const Pathname & root_r )
 
 3125        std::string ret( firstNonEmptyLineIn( root_r / 
"/var/lib/zypp/AnonymousUniqueId" ) );
 
 3126        if ( ret.
empty() && root_r != 
"/" )
 
 3129          ret = firstNonEmptyLineIn( 
"/var/lib/zypp/AnonymousUniqueId" );
 
 3137      return guessAnonymousUniqueId( 
root() );
 
 
 3142      return guessAnonymousUniqueId( staticGuessRoot(root_r) );
 
 
 3149      MIL << 
"New VendorAttr: " << vendorAttr_r << endl;
 
 
#define MAXRPMMESSAGELINES
#define SUBST_IF(PAT, VAL)
const std::string & asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool compatibleWith(const Arch &targetArch_r) const
Compatibility relation.
bool operator()(const zypp::Arch &lhs, const zypp::Arch &rhs) const
Default order for std::container based Arch::compare.
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
reference value() const
Reference to the Tp object.
void resetDispose()
Set no dispose function.
Store and operate on date (time_t).
static Date now()
Return the current time.
Edition represents [epoch:]version[-release]
std::string version() const
Version.
unsigned int epoch_t
Type of an epoch.
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 ...
int close() override
Wait for the progamm to complete.
const std::string & command() const
The command we're executing.
std::vector< std::string > Arguments
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
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
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.
static ResPool instance()
Singleton ctor.
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.
EstablishedStates establishedStates() const
Factory for EstablishedStates.
void getHardLockQueries(HardLockQueries &activeLocks_r)
Suggest a new set of queries based on the current selection.
EstablishedStates::ChangedPseudoInstalled ChangedPseudoInstalled
Map holding pseudo installed items where current and established status differ.
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.
Arch systemArchitecture() const
The system architecture zypp uses.
static ZConfig & instance()
Singleton ctor.
Options and policies for ZYpp::commit.
ZYppCommitPolicy & rpmInstFlags(target::rpm::RpmInstFlags newFlags_r)
The default target::rpm::RpmInstFlags.
bool singleTransModeEnabled() const
Whether the single_rpmtrans backend is enabled (or the classic_rpmtrans)
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.
ZYpp::Ptr getZYpp()
Convenience to get the Pointer to the ZYpp instance.
static zypp::Pathname lockfileDir()
Typesafe passing of user data via callbacks.
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
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.
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.
void add(Value val_r)
Push JSON Value to Array.
void add(String key_r, Value val_r)
Add key/value pair.
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.
detail::IdType value_type
void push(value_type val_r)
Push a value to the end off the Queue.
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.
pool::PoolTraits::HardLockQueries Data
Save and restore locale set from file.
const LocaleSet & locales() const
Return the loacale set.
void tryLevel(target::rpm::InstallResolvableReport::RpmLevel level_r)
Extract and remember posttrans scripts for later execution.
void executeScripts(rpm::RpmDb &rpm_r, const IdStringSet &obsoletedPackages_r)
Execute the remembered scripts and/or or dump_posttrans lines.
void discardScripts()
Discard all remembered scripts and/or or dump_posttrans lines.
bool aborted() const
Returns true if removing is aborted during progress.
std::unordered_set< IdString > Data
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.
std::list< PoolItem > PoolItemList
list of pool items
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.
rpm::RpmDb _rpm
RPM database.
~TargetImpl() override
Dtor.
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.
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
const Pathname & root() const
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
const Pathname & dbPath() const
Subclass to retrieve rpm database content.
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
SignalProxy< void(uint)> sigChannelReadyRead()
SignalProxy< void(int)> sigFinished()
SignalProxy< void()> sigMessageReceived()
static Ptr create(IODevice::Ptr iostr)
Namespace intended to collect all environment variables we use.
bool TRANSACTIONAL_UPDATE()
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
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 unlink(const Pathname &path)
Like 'unlink'.
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
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 assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
std::string md5sum(const Pathname &file)
Compute a files md5sum.
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
int touch(const Pathname &path)
Change file's modification and access times.
std::string getline(std::istream &str)
Read one line from stream.
json::Value toJSON(const sat::Transaction::Step &step_r)
See commitbegin on page plugin-commit for the specs.
bool empty() const
Whether neither idents nor provides are set.
Queue StringQueue
Queue with String ids.
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.
std::string toLower(const std::string &s)
Return lowercase version of s.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t", bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
std::string trim(const std::string &s, const Trim trim_r)
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
std::string rpmDbStateHash(const Pathname &root_r)
void writeUpgradeTestcase()
static bool fileMissing(const Pathname &pathname)
helper functor
void updateFileContent(const Pathname &filename, boost::function< bool()> condition, boost::function< std::string()> value)
updates the content of filename if condition is true, setting the content the the value returned by v...
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
static std::string generateRandomId()
generates a random id using uuidgen
Easy-to use interface to the ZYPP dependency resolver.
std::unordered_set< Locale > LocaleSet
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
std::list< UpdateNotificationFile > UpdateNotifications
std::unordered_set< IdString > IdStringSet
ResTraits< TRes >::PtrType make(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
std::string asString(const Patch::Category &obj)
ResTraits< TRes >::PtrType asKind(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
@ DownloadDefault
libzypp will decide what to do.
zypp::callback::UserData UserData
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
Temporarily set/unset an environment variable.
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.
@ RPM_NODEPS_FORCE
only this one used
static std::optional< Pipe > create(int flags=0)
#define NON_COPYABLE(CLASS)
Delete copy ctor and copy assign.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define NON_MOVABLE(CLASS)
Delete move ctor and move assign.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
#define IMPL_PTR_TYPE(NAME)