19 #include <sys/types.h>
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>
97 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) ->
void {
98 ::solv_chksum_free( chk,
nullptr );
100 if ( ::rpm_hash_database_state( state, chk ) == 0 )
103 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
107 WAR <<
"rpm_hash_database_state failed" << endl;
127 inline void sigMultiversionSpecChanged()
145 for (
const Transaction::Step & step : steps_r )
147 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
157 static const std::string strType(
"type" );
158 static const std::string strStage(
"stage" );
159 static const std::string strSolvable(
"solvable" );
161 static const std::string strTypeDel(
"-" );
162 static const std::string strTypeIns(
"+" );
163 static const std::string strTypeMul(
"M" );
165 static const std::string strStageDone(
"ok" );
166 static const std::string strStageFailed(
"err" );
168 static const std::string strSolvableN(
"n" );
169 static const std::string strSolvableE(
"e" );
170 static const std::string strSolvableV(
"v" );
171 static const std::string strSolvableR(
"r" );
172 static const std::string strSolvableA(
"a" );
179 case Transaction::TRANSACTION_IGNORE:
break;
180 case Transaction::TRANSACTION_ERASE: ret.
add( strType, strTypeDel );
break;
181 case Transaction::TRANSACTION_INSTALL: ret.
add( strType, strTypeIns );
break;
182 case Transaction::TRANSACTION_MULTIINSTALL: ret.
add( strType, strTypeMul );
break;
187 case Transaction::STEP_TODO:
break;
188 case Transaction::STEP_DONE: ret.
add( strStage, strStageDone );
break;
189 case Transaction::STEP_ERROR: ret.
add( strStage, strStageFailed );
break;
198 ident = solv.ident();
205 ident = step_r.
ident();
207 arch = step_r.
arch();
212 { strSolvableV, ed.
version() },
213 { strSolvableR, ed.
release() },
217 s.add( strSolvableE, epoch );
219 ret.
add( strSolvable, s );
235 class AssertProcMounted
241 AssertProcMounted( Pathname root_r )
244 if ( ! PathInfo(root_r/
"self").isDir() ) {
245 MIL <<
"Try to make sure proc is mounted at" <<
_mountpoint << endl;
247 && execute({
"mount",
"-t",
"proc",
"proc", root_r.asString() }) == 0 ) {
256 ~AssertProcMounted( )
260 MIL <<
"We mounted " <<
_mountpoint <<
" so we unmount it" << endl;
261 execute({
"umount",
"-l",
_mountpoint.asString() });
269 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
288 std::ifstream infile( historyFile_r.c_str() );
289 for( iostr::EachLine in( infile ); in; in.next() )
291 const char * ch( (*in).c_str() );
293 if ( *ch <
'1' ||
'9' < *ch )
295 const char * sep1 = ::strchr( ch,
'|' );
300 bool installs =
true;
301 if ( ::strncmp( sep1,
"install|", 8 ) )
303 if ( ::strncmp( sep1,
"remove |", 8 ) )
310 const char * sep2 = ::strchr( sep1,
'|' );
311 if ( !sep2 || sep1 == sep2 )
313 (*in)[sep2-ch] =
'\0';
314 IdString pkg( sep1 );
318 onSystemByUserList.erase( pkg );
322 if ( (sep1 = ::strchr( sep2+1,
'|' ))
323 && (sep1 = ::strchr( sep1+1,
'|' ))
324 && (sep2 = ::strchr( sep1+1,
'|' )) )
326 (*in)[sep2-ch] =
'\0';
327 if ( ::strchr( sep1+1,
'@' ) )
330 onSystemByUserList.insert( pkg );
335 MIL <<
"onSystemByUserList found: " << onSystemByUserList.size() << endl;
336 return onSystemByUserList;
346 return PluginFrame( command_r, json::Object {
347 {
"TransactionStepList", steps_r }
357 MIL <<
"Testcases to keep: " << toKeep << endl;
360 Target_Ptr target( getZYpp()->getTarget() );
363 WAR <<
"No Target no Testcase!" << endl;
367 std::string stem(
"updateTestcase" );
368 Pathname dir( target->assertRootPrefix(
"/var/log/") );
372 std::list<std::string> content;
374 std::set<std::string> cases;
375 for_( c, content.begin(), content.end() )
380 if ( cases.size() >= toKeep )
382 unsigned toDel = cases.size() - toKeep + 1;
383 for_( c, cases.begin(), cases.end() )
392 MIL <<
"Write new testcase " << next << endl;
393 getZYpp()->resolver()->createSolverTestcase( next.
asString(),
false );
410 std::pair<bool,PatchScriptReport::Action> doExecuteScript(
const Pathname & root_r,
420 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
425 WAR <<
"User request to abort script " << script_r << endl;
434 if ( prog.close() != 0 )
436 ret.second = report_r->problem( prog.execError() );
437 WAR <<
"ACTION" << ret.second <<
"(" << prog.execError() <<
")" << endl;
438 std::ostringstream sstr;
439 sstr << script_r <<
_(
" execution failed") <<
" (" << prog.execError() <<
")" << endl;
440 historylog.
comment(sstr.str(),
true);
452 bool executeScript(
const Pathname & root_r,
453 const Pathname & script_r,
454 callback::SendReport<PatchScriptReport> & report_r )
459 action = doExecuteScript( root_r, script_r, report_r );
463 switch ( action.second )
466 WAR <<
"User request to abort at script " << script_r << endl;
471 WAR <<
"User request to skip script " << script_r << endl;
481 INT <<
"Abort on unknown ACTION request " << action.second <<
" returned" << endl;
490 bool RunUpdateScripts(
const Pathname & root_r,
491 const Pathname & scriptsPath_r,
492 const std::vector<sat::Solvable> & checkPackages_r,
495 if ( checkPackages_r.empty() )
498 MIL <<
"Looking for new update scripts in (" << root_r <<
")" << scriptsPath_r << endl;
500 if ( ! PathInfo( scriptsDir ).isDir() )
503 std::list<std::string> scripts;
505 if ( scripts.empty() )
513 std::map<std::string, Pathname> unify;
514 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
516 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
517 for_( sit, scripts.begin(), scripts.end() )
522 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
525 PathInfo script( scriptsDir / *sit );
526 Pathname localPath( scriptsPath_r/(*sit) );
527 std::string unifytag;
529 if ( script.isFile() )
535 else if ( ! script.isExist() )
543 if ( unifytag.empty() )
547 if ( unify[unifytag].empty() )
549 unify[unifytag] = localPath;
556 std::string msg(
str::form(
_(
"%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
557 MIL <<
"Skip update script: " << msg << endl;
558 HistoryLog().comment( msg,
true );
562 if ( abort || aborting_r )
564 WAR <<
"Aborting: Skip update script " << *sit << endl;
565 HistoryLog().comment(
566 localPath.asString() +
_(
" execution skipped while aborting"),
571 MIL <<
"Found update script " << *sit << endl;
572 callback::SendReport<PatchScriptReport> report;
573 report->start( make<Package>( *it ), script.path() );
575 if ( ! executeScript( root_r, localPath, report ) )
587 inline void copyTo( std::ostream & out_r,
const Pathname & file_r )
589 std::ifstream infile( file_r.c_str() );
590 for( iostr::EachLine in( infile ); in; in.next() )
592 out_r << *in << endl;
596 inline std::string notificationCmdSubst(
const std::string & cmd_r,
const UpdateNotificationFile & notification_r )
598 std::string ret( cmd_r );
599 #define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
600 SUBST_IF(
"%p", notification_r.solvable().asString() );
601 SUBST_IF(
"%P", notification_r.file().asString() );
606 void sendNotification(
const Pathname & root_r,
609 if ( notifications_r.empty() )
613 MIL <<
"Notification command is '" << cmdspec <<
"'" << endl;
614 if ( cmdspec.empty() )
618 if ( pos == std::string::npos )
620 ERR <<
"Can't send Notification: Missing 'format |' in command spec." << endl;
621 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
626 std::string commandStr(
str::trim( cmdspec.substr( pos + 1 ) ) );
628 enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
629 Format format = UNKNOWN;
630 if ( formatStr ==
"none" )
632 else if ( formatStr ==
"single" )
634 else if ( formatStr ==
"digest" )
636 else if ( formatStr ==
"bulk" )
640 ERR <<
"Can't send Notification: Unknown format '" << formatStr <<
" |' in command spec." << endl;
641 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
649 if ( format == NONE || format == SINGLE )
651 for_( it, notifications_r.begin(), notifications_r.end() )
653 std::vector<std::string> command;
654 if ( format == SINGLE )
656 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
661 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
665 int ret = prog.close();
668 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
669 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
675 else if ( format == DIGEST || format == BULK )
677 filesystem::TmpFile tmpfile;
678 std::ofstream out( tmpfile.path().c_str() );
679 for_( it, notifications_r.begin(), notifications_r.end() )
681 if ( format == DIGEST )
683 out << it->file() << endl;
685 else if ( format == BULK )
691 std::vector<std::string> command;
692 command.push_back(
"<"+tmpfile.path().asString() );
693 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
698 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
702 int ret = prog.close();
705 ERR <<
"Notification command returned with error (" << ret <<
")." << endl;
706 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
713 INT <<
"Can't send Notification: Missing handler for 'format |' in command spec." << endl;
714 HistoryLog().comment( str::Str() <<
_(
"Error sending update message notification."),
true );
725 void RunUpdateMessages(
const Pathname & root_r,
726 const Pathname & messagesPath_r,
727 const std::vector<sat::Solvable> & checkPackages_r,
728 ZYppCommitResult & result_r )
730 if ( checkPackages_r.empty() )
733 MIL <<
"Looking for new update messages in (" << root_r <<
")" << messagesPath_r << endl;
735 if ( ! PathInfo( messagesDir ).isDir() )
738 std::list<std::string> messages;
740 if ( messages.empty() )
746 HistoryLog historylog;
747 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
749 std::string prefix(
str::form(
"%s-%s", it->name().c_str(), it->edition().c_str() ) );
750 for_( sit, messages.begin(), messages.end() )
755 if ( (*sit)[prefix.size()] !=
'\0' && (*sit)[prefix.size()] !=
'-' )
758 PathInfo message( messagesDir / *sit );
759 if ( ! message.isFile() || message.size() == 0 )
762 MIL <<
"Found update message " << *sit << endl;
763 Pathname localPath( messagesPath_r/(*sit) );
764 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
765 historylog.comment( str::Str() <<
_(
"New update message") <<
" " << localPath,
true );
768 sendNotification( root_r, result_r.updateMessages() );
774 void logPatchStatusChanges(
const sat::Transaction & transaction_r, TargetImpl & target_r )
777 if ( changedPseudoInstalled.empty() )
785 WAR <<
"Need to recompute the patch status changes as commit is incomplete!" << endl;
791 HistoryLog historylog;
792 for (
const auto & el : changedPseudoInstalled )
793 historylog.patchStateChange( el.first, el.second );
802 const std::vector<sat::Solvable> & checkPackages_r,
804 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
817 , _requestedLocalesFile( home() /
"RequestedLocales" )
818 , _autoInstalledFile( home() /
"AutoInstalled" )
827 sigMultiversionSpecChanged();
828 MIL <<
"Initialized target on " <<
_root << endl;
836 std::ifstream uuidprovider(
"/proc/sys/kernel/random/uuid" );
846 boost::function<
bool ()> condition,
847 boost::function<std::string ()> value )
849 std::string val = value();
857 MIL <<
"updating '" << filename <<
"' content." << endl;
861 std::ofstream filestr;
864 filestr.open( filename.
c_str() );
866 if ( filestr.good() )
902 WAR <<
"Can't create anonymous id file" << endl;
911 Pathname flavorpath(
home() /
"LastDistributionFlavor");
917 WAR <<
"No base product, I won't create flavor cache" << endl;
921 std::string flavor = p->flavor();
933 WAR <<
"Can't create flavor cache" << endl;
946 sigMultiversionSpecChanged();
947 MIL <<
"Targets closed" << endl;
971 Pathname rpmsolvcookie = base/
"cookie";
973 bool build_rpm_solv =
true;
983 MIL <<
"Read cookie: " << cookie << endl;
988 if ( status == rpmstatus )
989 build_rpm_solv =
false;
990 MIL <<
"Read cookie: " << rpmsolvcookie <<
" says: "
991 << (build_rpm_solv ?
"outdated" :
"uptodate") << endl;
995 if ( build_rpm_solv )
1009 bool switchingToTmpSolvfile =
false;
1010 Exception ex(
"Failed to cache rpm database.");
1016 rpmsolv = base/
"solv";
1017 rpmsolvcookie = base/
"cookie";
1024 WAR <<
"Using a temporary solv file at " << base << endl;
1025 switchingToTmpSolvfile =
true;
1034 if ( ! switchingToTmpSolvfile )
1044 cmd.push_back(
"rpmdb2solv" );
1046 cmd.push_back(
"-r" );
1049 cmd.push_back(
"-D" );
1051 cmd.push_back(
"-X" );
1053 cmd.push_back(
"-p" );
1056 if ( ! oldSolvFile.
empty() )
1057 cmd.push_back( oldSolvFile.
asString() );
1059 cmd.push_back(
"-o" );
1063 std::string errdetail;
1066 WAR <<
" " << output;
1067 if ( errdetail.empty() ) {
1071 errdetail += output;
1074 int ret = prog.
close();
1095 if (
root() ==
"/" )
1106 if ( !
PathInfo(base/
"solv.idx").isExist() )
1109 return build_rpm_solv;
1127 MIL <<
"New cache built: " << (newCache?
"true":
"false") <<
1128 ", force loading: " << (force?
"true":
"false") << endl;
1133 MIL <<
"adding " << rpmsolv <<
" to pool(" << satpool.
systemRepoAlias() <<
")" << endl;
1140 if ( newCache || force )
1157 MIL <<
"adding " << rpmsolv <<
" to system" << endl;
1163 MIL <<
"Try to handle exception by rebuilding the solv-file" << endl;
1188 if (
PathInfo( historyFile ).isExist() )
1195 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1196 onSystemByAuto.insert( ident );
1218 if (
PathInfo( needrebootFile ).isFile() )
1219 needrebootSpec.
parseFrom( needrebootFile );
1222 if (
PathInfo( needrebootDir ).isDir() )
1227 [&](
const Pathname & dir_r,
const char *
const str_r )->
bool
1229 if ( ! isRpmConfigBackup( str_r ) )
1231 Pathname needrebootFile { needrebootDir / str_r };
1232 if (
PathInfo( needrebootFile ).isFile() )
1233 needrebootSpec.
parseFrom( needrebootFile );
1244 if ( ! hardLocks.empty() )
1253 MIL <<
"Target loaded: " << system.
solvablesSize() <<
" resolvables" << endl;
1265 bool explicitDryRun = policy_r.
dryRun();
1275 if (
root() ==
"/" )
1289 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
")" << endl;
1308 steps.push_back( *it );
1315 MIL <<
"Todo: " << result << endl;
1325 if ( commitPlugins )
1326 commitPlugins.
send( transactionPluginFrame(
"COMMITBEGIN", steps ) );
1333 if ( ! policy_r.
dryRun() )
1339 DBG <<
"dryRun: Not writing upgrade testcase." << endl;
1346 if ( ! policy_r.
dryRun() )
1368 DBG <<
"dryRun: Not stroring non-package data." << endl;
1375 if ( ! policy_r.
dryRun() )
1377 for_( it, steps.begin(), steps.end() )
1379 if ( ! it->satSolvable().isKind<
Patch>() )
1387 if ( ! patch ||patch->message().empty() )
1390 MIL <<
"Show message for " << patch << endl;
1392 if ( ! report->show( patch ) )
1394 WAR <<
"commit aborted by the user" << endl;
1401 DBG <<
"dryRun: Not checking patch messages." << endl;
1423 for_( it, steps.begin(), steps.end() )
1425 switch ( it->stepType() )
1444 localfile = packageCache.
get( pi );
1447 catch (
const AbortRequestException & exp )
1451 WAR <<
"commit cache preload aborted by the user" << endl;
1455 catch (
const SkipRequestException & exp )
1460 WAR <<
"Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1470 INT <<
"Unexpected Error: Skipping cache preload package " << pi->asKind<
Package>() <<
" in commit" << endl;
1480 ERR <<
"Some packages could not be provided. Aborting commit."<< endl;
1488 if ( ! policy_r.
dryRun() )
1492 commit( policy_r, packageCache, result );
1496 DBG <<
"dryRun/downloadOnly: Not installing/deleting anything." << endl;
1497 if ( explicitDryRun ) {
1507 DBG <<
"dryRun: Not downloading/installing/deleting anything." << endl;
1508 if ( explicitDryRun ) {
1520 WAR <<
"(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1529 if ( commitPlugins )
1530 commitPlugins.
send( transactionPluginFrame(
"COMMITEND", steps ) );
1535 if ( ! policy_r.
dryRun() )
1540 MIL <<
"TargetImpl::commit(<pool>, " << policy_r <<
") returns: " << result << endl;
1551 struct NotifyAttemptToModify
1569 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1574 NotifyAttemptToModify attemptToModify( result_r );
1579 AssertProcMounted assertProcMounted(
_root );
1582 std::vector<sat::Solvable> successfullyInstalledPackages;
1585 for_( step, steps.begin(), steps.end() )
1607 localfile = packageCache_r.
get( citem );
1609 catch (
const AbortRequestException &e )
1611 WAR <<
"commit aborted by the user" << endl;
1616 catch (
const SkipRequestException &e )
1619 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1628 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1637 bool success =
false;
1665 WAR <<
"commit aborted by the user" << endl;
1674 auto rebootNeededFile =
root() /
"/run/reboot-needed";
1690 WAR <<
"dry run failed" << endl;
1697 WAR <<
"commit aborted by the user" << endl;
1702 WAR <<
"Install failed" << endl;
1708 if ( success && !policy_r.
dryRun() )
1711 successfullyInstalledPackages.push_back( citem.
satSolvable() );
1720 bool success =
false;
1733 WAR <<
"commit aborted by the user" << endl;
1749 WAR <<
"commit aborted by the user" << endl;
1755 WAR <<
"removal of " << p <<
" failed";
1758 if ( success && !policy_r.
dryRun() )
1765 else if ( ! policy_r.
dryRun() )
1769 if ( ! citem.
buddy() )
1776 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
1782 std::string referenceFilename( p->referenceFilename() );
1783 if ( referenceFilename.empty() )
1785 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1789 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
1790 if ( !
rpm().hasFile( referencePath.asString() ) )
1795 ERR <<
"Delete orphan product failed: " << referencePath << endl;
1799 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
1826 if ( ! successfullyInstalledPackages.empty() )
1829 successfullyInstalledPackages, abort ) )
1831 WAR <<
"Commit aborted by the user" << endl;
1837 successfullyInstalledPackages,
1844 logPatchStatusChanges( result_r.
transaction(), *
this );
1861 namespace zpt = zypp::proto::target;
1864 MIL <<
"TargetImpl::commit(<list>" << policy_r <<
")" << steps.size() << endl;
1869 NotifyAttemptToModify attemptToModify( result_r );
1875 AssertProcMounted assertProcMounted(
_root );
1880 commit.set_flags( flags );
1887 std::vector<ManagedFile> locFiles;
1891 auto &step = steps[stepId];
1908 locFiles.push_back( packageCache_r.
get( citem ) );
1910 zpt::TransactionStep tStep;
1911 tStep.set_stepid( stepId );
1912 tStep.mutable_install()->set_pathname( locFiles.back()->asString() );
1913 tStep.mutable_install()->set_multiversion( p->multiversionInstall() );
1915 *
commit.mutable_steps()->Add( ) = std::move(tStep);
1917 catch (
const AbortRequestException &e )
1919 WAR <<
"commit aborted by the user" << endl;
1924 catch (
const SkipRequestException &e )
1927 WAR <<
"Skipping package " << p <<
" in commit" << endl;
1936 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1942 zpt::TransactionStep tStep;
1943 tStep.set_stepid( stepId );
1944 tStep.mutable_remove()->set_name( p->name() );
1945 tStep.mutable_remove()->set_version( p->edition().version() );
1946 tStep.mutable_remove()->set_release( p->edition().release() );
1947 tStep.mutable_remove()->set_arch( p->arch().asString() );
1949 *
commit.mutable_steps()->Add() = std::move(tStep);
1960 zpt::TransactionStep tStep;
1961 tStep.set_stepid( stepId );
1962 tStep.mutable_install()->set_pathname( locFiles.back()->asString() );
1963 tStep.mutable_install()->set_multiversion(
false );
1964 *
commit.mutable_steps()->Add() = std::move(tStep);
1968 INT <<
"Unexpected Error: Skipping package " << p <<
" in commit" << endl;
1975 std::vector<sat::Solvable> successfullyInstalledPackages;
1977 if (
commit.steps_size() ) {
1980 auto loop = zyppng::EventLoop::create();
1989 int currentStepId = -1;
1995 bool gotEndOfScript =
false;
1998 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
1999 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2000 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2001 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2002 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2005 std::optional<zpt::TransactionError> transactionError;
2008 std::string currentScriptType;
2009 std::string currentScriptPackage;
2019 unsigned lineno = 0;
2022 auto msgSource = zyppng::AsyncDataSource::create();
2023 auto scriptSource = zyppng::AsyncDataSource::create();
2028 const auto &sendRpmLineToReport = [&]( std::string line ){
2030 const auto &sendLogRep = [&](
auto &report,
const auto &cType ){
2032 if ( currentStepId >= 0 )
2033 cmdout.
set(
"solvable", steps.at(currentStepId).satSolvable() );
2034 cmdout.
set(
"line", line );
2035 report->report(cmdout);
2038 if ( installreport ) {
2040 }
else if ( uninstallreport ) {
2042 }
else if ( scriptreport ) {
2044 }
else if ( transactionreport ) {
2046 }
else if ( cleanupreport ) {
2049 WAR <<
"Got rpm output without active report " << line << std::endl;
2054 if ( line.find(
" scriptlet failed, " ) == std::string::npos )
2058 if ( line.back() !=
'\n' )
2064 const auto &processDataFromScriptFd = [&](){
2066 while ( scriptSource->canReadLine() ) {
2068 if ( gotEndOfScript )
2071 std::string l = scriptSource->readLine().asString();
2073 DBG <<
"Received end of script tag" << std::endl;
2074 gotEndOfScript =
true;
2075 l = l.substr( 0, l.size() - endOfScriptTag.size() );
2076 if ( l.size() == 0 )
2080 sendRpmLineToReport( l );
2083 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2086 const auto &waitForScriptEnd = [&]() {
2089 if ( gotEndOfScript )
2093 processDataFromScriptFd();
2096 while ( scriptSource->canRead() && !gotEndOfScript ) {
2099 scriptSource->waitForReadyRead( 100 );
2103 const auto &aboutToStartNewReport = [&](){
2105 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2106 ERR <<
"There is still a running report, this is a bug" << std::endl;
2110 DBG <<
"Starting new report, setting gotEndOfScript to false" << std::endl;
2111 gotEndOfScript =
false;
2114 const auto &writeRpmMsgToHistory = [&](){
2115 if ( rpmmsg.size() == 0 )
2119 rpmmsg +=
"[truncated]\n";
2121 std::ostringstream sstr;
2122 sstr <<
"rpm output:" << endl << rpmmsg << endl;
2127 const auto &finalizeCurrentReport = [&]() {
2130 if ( currentStepId >= 0 ) {
2131 step = &steps.at(currentStepId);
2135 if ( installreport ) {
2143 writeRpmMsgToHistory();
2147 ( *installreport)->progress( 100, resObj );
2150 successfullyInstalledPackages.push_back( step->
satSolvable() );
2156 auto rebootNeededFile =
root() /
"/run/reboot-needed";
2168 writeRpmMsgToHistory();
2171 if ( uninstallreport ) {
2179 writeRpmMsgToHistory();
2183 ( *uninstallreport)->progress( 100, resObj );
2193 writeRpmMsgToHistory();
2196 if ( scriptreport ) {
2198 ( *scriptreport)->progress( 100, resObj );
2201 if ( transactionreport ) {
2203 ( *transactionreport)->progress( 100 );
2206 if ( cleanupreport ) {
2208 ( *cleanupreport)->progress( 100 );
2211 DBG <<
"Report finalized" << std::endl;
2215 currentScriptType.clear();
2216 currentScriptPackage.clear();
2217 installreport.reset();
2218 uninstallreport.reset();
2219 scriptreport.reset();
2220 transactionreport.reset();
2221 cleanupreport.reset();
2231 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2233 const char *argv[] = {
2236 zyppRpmBinary.data(),
2239 auto prog = zyppng::Process::create();
2243 auto messagePipe = zyppng::Pipe::create();
2249 auto scriptPipe = zyppng::Pipe::create();
2253 prog->addFd( messagePipe->writeFd );
2254 prog->addFd( scriptPipe->writeFd );
2257 if ( !scriptSource->open( scriptPipe->readFd ) )
2260 prog->sigStarted().connect( [&](){
2263 messagePipe->unrefWrite();
2264 scriptPipe->unrefWrite();
2267 prog->stdoutDevice()->connectFunc( &zyppng::IODevice::sigReadyRead, [&](){
2268 while( prog->stdoutDevice()->canReadLine() ) {
2269 MIL <<
"zypp-rpm stdout: " << prog->stdoutDevice()->readLine().asStringView() << std::endl;
2274 prog->stderrDevice()->connectFunc( &zyppng::IODevice::sigReadyRead, [&](){
2275 while( prog->stderrDevice()->canReadLine() ) {
2276 MIL <<
"zypp-rpm stderr: " << prog->stderrDevice()->readLine().asStringView() << std::endl;
2282 const auto outFd = prog->stdinFd();
2289 zyppng::rpc::HeaderSizeType msgSize =
commit.ByteSizeLong();
2290 const auto written = zyppng::eintrSafeCall( ::
write, outFd, &msgSize,
sizeof(zyppng::rpc::HeaderSizeType) );
2291 if ( written !=
sizeof(zyppng::rpc::HeaderSizeType) ) {
2292 prog->stop( SIGKILL );
2296 zyppng::FileOutputStream fo ( outFd );
2297 if ( !
commit.SerializeToZeroCopyStream( &fo ) ) {
2298 prog->stop( SIGKILL );
2308 if ( !msgSource->open( messagePipe->readFd ) )
2311 size_t pendingMessageSize = 0;
2312 const auto &processMessages = [&] ( ) {
2316 const auto &parseMsgWithStepId = [&steps](
const auto &m,
auto &p ){
2317 if ( !p.ParseFromString( m.value() ) ) {
2318 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2322 auto id = p.stepid();
2323 if ( id < 0 || id >= steps.size() ) {
2324 ERR <<
"Received invalid stepId: " <<
id <<
" in " << m.messagetypename() <<
" message from zypp-rpm, ignoring." << std::endl;
2330 while ( msgSource->bytesAvailable() ) {
2332 if ( pendingMessageSize == 0 ) {
2333 if ( msgSource->bytesAvailable() >=
sizeof( zyppng::rpc::HeaderSizeType ) ) {
2334 msgSource->read(
reinterpret_cast<char *
>( &pendingMessageSize ),
sizeof( zyppng::rpc::HeaderSizeType ) );
2338 if ( msgSource->bytesAvailable() < pendingMessageSize ) {
2342 auto bytes = msgSource->read( pendingMessageSize );
2343 pendingMessageSize = 0;
2345 zypp::proto::Envelope m;
2346 if (! m.ParseFromArray( bytes.data(), bytes.size() ) ) {
2349 ERR <<
"Received misformed message from zypp-rpm, ignoring" << std::endl;
2357 const auto &mName = m.messagetypename();
2358 if ( mName ==
"zypp.proto.target.RpmLog" ) {
2361 if ( !p.ParseFromString( m.value() ) ) {
2362 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2366 sendRpmLineToReport( p.line() );
2369 }
else if ( mName ==
"zypp.proto.target.PackageBegin" ) {
2370 finalizeCurrentReport();
2372 zpt::PackageBegin p;
2373 if ( !parseMsgWithStepId( m, p ) )
2376 aboutToStartNewReport();
2378 auto & step = steps.at( p.stepid() );
2379 currentStepId = p.stepid();
2381 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2382 ( *uninstallreport )->start(
makeResObject( step.satSolvable() ) );
2384 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2385 ( *installreport )->start(
makeResObject( step.satSolvable() ) );
2388 }
else if ( mName ==
"zypp.proto.target.PackageFinished" ) {
2389 zpt::PackageFinished p;
2390 if ( !parseMsgWithStepId( m, p ) )
2393 if ( p.stepid() < 0 || p.stepid() > steps.size() )
2400 }
else if ( mName ==
"zypp.proto.target.PackageProgress" ) {
2401 zpt::PackageProgress p;
2402 if ( !parseMsgWithStepId( m, p ) )
2405 if ( uninstallreport )
2406 (*uninstallreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2407 else if ( installreport )
2408 (*installreport)->progress( p.amount(),
makeResObject( steps.at( p.stepid() ) ));
2410 ERR <<
"Received a " << mName <<
" message but there is no corresponding report running." << std::endl;
2412 }
else if ( mName ==
"zypp.proto.target.PackageError" ) {
2413 zpt::PackageError p;
2414 if ( !parseMsgWithStepId( m, p ) )
2417 if ( p.stepid() >= 0 && p.stepid() < steps.size() )
2420 finalizeCurrentReport();
2422 }
else if ( mName ==
"zypp.proto.target.ScriptBegin" ) {
2423 finalizeCurrentReport();
2426 if ( !p.ParseFromString( m.value() ) ) {
2427 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2431 aboutToStartNewReport();
2434 const auto stepId = p.stepid();
2435 if ( stepId >= 0 && stepId < steps.size() ) {
2439 currentStepId = p.stepid();
2440 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2441 currentScriptType = p.scripttype();
2442 currentScriptPackage = p.scriptpackage();
2443 (*scriptreport)->start( p.scripttype(), p.scriptpackage(), resPtr );
2445 }
else if ( mName ==
"zypp.proto.target.ScriptFinished" ) {
2448 MIL <<
"Received" << mName <<
" from zypp-rpm" << std::endl;
2450 }
else if ( mName ==
"zypp.proto.target.ScriptError" ) {
2453 if ( !p.ParseFromString( m.value() ) ) {
2454 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2459 const auto stepId = p.stepid();
2460 if ( stepId >= 0 && stepId < steps.size() ) {
2470 str::form(
"Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() :
"unknown" ),
2473 writeRpmMsgToHistory();
2475 if ( !scriptreport ) {
2476 ERR <<
"Received a ScriptError message, but there is no running report. " << std::endl;
2485 scriptreport.reset();
2488 }
else if ( mName ==
"zypp.proto.target.CleanupBegin" ) {
2489 finalizeCurrentReport();
2491 zpt::CleanupBegin beg;
2492 if ( !beg.ParseFromString( m.value() ) ) {
2493 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2497 aboutToStartNewReport();
2498 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2499 (*cleanupreport)->start( beg.nvra() );
2500 }
else if ( mName ==
"zypp.proto.target.CleanupFinished" ) {
2502 finalizeCurrentReport();
2504 }
else if ( mName ==
"zypp.proto.target.CleanupProgress" ) {
2505 zpt::CleanupProgress prog;
2506 if ( !prog.ParseFromString( m.value() ) ) {
2507 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2511 if ( !cleanupreport ) {
2512 ERR <<
"Received a CleanupProgress message, but there is no running report. " << std::endl;
2516 (*cleanupreport)->progress( prog.amount() );
2518 }
else if ( mName ==
"zypp.proto.target.TransBegin" ) {
2519 finalizeCurrentReport();
2521 zpt::TransBegin beg;
2522 if ( !beg.ParseFromString( m.value() ) ) {
2523 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2527 aboutToStartNewReport();
2528 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2529 (*transactionreport)->start( beg.name() );
2530 }
else if ( mName ==
"zypp.proto.target.TransFinished" ) {
2532 finalizeCurrentReport();
2534 }
else if ( mName ==
"zypp.proto.target.TransProgress" ) {
2535 zpt::TransProgress prog;
2536 if ( !prog.ParseFromString( m.value() ) ) {
2537 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2541 if ( !transactionreport ) {
2542 ERR <<
"Received a TransactionProgress message, but there is no running report. " << std::endl;
2546 (*transactionreport)->progress( prog.amount() );
2547 }
else if ( mName ==
"zypp.proto.target.TransactionError" ) {
2549 zpt::TransactionError error;
2550 if ( !error.ParseFromString( m.value() ) ) {
2551 ERR <<
"Failed to parse " << m.messagetypename() <<
" message from zypp-rpm." << std::endl;
2556 transactionError = std::move(error);
2559 ERR <<
"Received unexpected message from zypp-rpm: "<< m.messagetypename() <<
", ignoring" << std::endl;
2565 msgSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, processMessages );
2568 int zyppRpmExitCode = -1;
2569 prog->connectFunc( &zyppng::Process::sigFinished, [&](
int code ){
2570 zyppRpmExitCode = code;
2574 if ( !prog->start( argv ) ) {
2585 finalizeCurrentReport();
2588 bool readMsgs =
false;
2589 while( prog->stderrDevice()->canReadLine() ) {
2591 MIL <<
"zypp-rpm: " << prog->stderrDevice()->readLine().asStringView();
2593 while( prog->stdoutDevice()->canReadLine() ) {
2595 MIL <<
"zypp-rpm: " << prog->stdoutDevice()->readLine().asStringView();
2598 while ( scriptSource->canReadLine() ) {
2600 MIL <<
"rpm-script-fd: " << scriptSource->readLine().asStringView();
2602 if ( scriptSource->bytesAvailable() > 0 ) {
2604 MIL <<
"rpm-script-fd: " << scriptSource->readAll().asStringView();
2609 switch ( zyppRpmExitCode ) {
2611 case zypprpm::NoError:
2612 case zypprpm::RpmFinishedWithError:
2614 case zypprpm::RpmFinishedWithTransactionError: {
2616 if ( transactionError ) {
2618 std::ostringstream sstr;
2619 sstr <<
_(
"Executing the transaction failed because of the following problems:") <<
"\n";
2620 for (
const auto & err : transactionError->problems() ) {
2621 sstr <<
" " << err.message() <<
"\n";
2631 case zypprpm::FailedToOpenDb:
2634 case zypprpm::WrongHeaderSize:
2635 case zypprpm::WrongMessageFormat:
2638 case zypprpm::RpmInitFailed:
2641 case zypprpm::FailedToReadPackage:
2644 case zypprpm::FailedToAddStepToTransaction:
2650 auto &step = steps[stepId];
2662 ERR <<
"Can't install orphan product without release-package! " << citem << endl;
2666 std::string referenceFilename( p->referenceFilename() );
2668 if ( referenceFilename.empty() ) {
2669 ERR <<
"Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2671 Pathname referencePath {
Pathname(
"/etc/products.d") / referenceFilename };
2673 if ( !
rpm().hasFile( referencePath.asString() ) ) {
2677 ERR <<
"Delete orphan product failed: " << referencePath << endl;
2679 WAR <<
"Won't remove orphan product: '/etc/products.d/" << referenceFilename <<
"' is owned by a package." << endl;
2693 if ( ! successfullyInstalledPackages.empty() )
2696 successfullyInstalledPackages, abort ) )
2698 WAR <<
"Commit aborted by the user" << endl;
2704 successfullyInstalledPackages,
2711 logPatchStatusChanges( result_r.
transaction(), *
this );
2739 if ( baseproduct.isFile() )
2752 ERR <<
"baseproduct symlink is dangling or missing: " << baseproduct << endl;
2757 inline Pathname staticGuessRoot(
const Pathname & root_r )
2759 if ( root_r.empty() )
2764 return Pathname(
"/");
2770 inline std::string firstNonEmptyLineIn(
const Pathname & file_r )
2772 std::ifstream idfile( file_r.c_str() );
2773 for( iostr::EachLine in( idfile ); in; in.next() )
2776 if ( ! line.empty() )
2779 return std::string();
2790 if ( p->isTargetDistribution() )
2798 const Pathname needroot( staticGuessRoot(root_r) );
2799 const Target_constPtr target( getZYpp()->getTarget() );
2800 if ( target && target->root() == needroot )
2801 return target->requestedLocales();
2807 MIL <<
"updateAutoInstalled if changed..." << endl;
2815 {
return baseproductdata(
_root ).registerTarget(); }
2818 {
return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
2821 {
return baseproductdata(
_root ).registerRelease(); }
2824 {
return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
2827 {
return baseproductdata(
_root ).registerFlavor(); }
2830 {
return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
2863 std::string
distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version();
2870 scoped_ptr<rpm::RpmDb> tmprpmdb;
2876 tmprpmdb->initDatabase( );
2893 return firstNonEmptyLineIn(
home() /
"LastDistributionFlavor" );
2898 return firstNonEmptyLineIn( staticGuessRoot(root_r) /
"/var/lib/zypp/LastDistributionFlavor" );
2904 std::string guessAnonymousUniqueId(
const Pathname & root_r )
2907 std::string ret( firstNonEmptyLineIn( root_r /
"/var/lib/zypp/AnonymousUniqueId" ) );
2908 if ( ret.
empty() && root_r !=
"/" )
2911 ret = firstNonEmptyLineIn(
"/var/lib/zypp/AnonymousUniqueId" );
2919 return guessAnonymousUniqueId(
root() );
2924 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
2931 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 & allMedia()
Process all media (default)
ZYppCommitPolicy & downloadMode(DownloadMode val_r)
Commit download policy to use.
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 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.
const char * c_str() const
String representation.
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.
void setLocales(const LocaleSet &locales_r)
Store a new locale set.
const LocaleSet & locales() const
Return the loacale 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 Pathname & file() const
Return the file path.
std::unordered_set< IdString > Data
const Data & data() const
Return the data.
void setData(const Data &data_r)
Store new Data.
Base class for concrete Target implementations.
std::string targetDistributionRelease() const
This is register.release attribute of the installed base product.
std::string targetDistribution() const
This is register.target attribute of the installed base product.
LocaleSet requestedLocales() const
Languages to be supported by the system.
void updateAutoInstalled()
Update the database of autoinstalled packages.
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Provides a source package on the Target.
Pathname _root
Path to the target.
RequestedLocalesFile _requestedLocalesFile
Requested Locales database.
void createLastDistributionFlavorCache() const
generates a cache of the last product flavor
Pathname _tmpSolvfilesPath
std::string _distributionVersion
Cache distributionVersion.
std::list< PoolItem > PoolItemList
list of pool items
rpm::RpmDb _rpm
RPM database.
rpm::RpmDb & rpm()
The RPM database.
Pathname solvfilesPath() const
The solv file location actually in use (default or temp).
std::string distributionVersion() const
This is version attribute of the installed base product.
const VendorAttr & vendorAttr() const
The targets current vendor equivalence settings.
void createAnonymousId() const
generates the unique anonymous id which is called when creating the target
SolvIdentFile _autoInstalledFile
user/auto installed database
Product::constPtr baseProduct() const
returns the target base installed product, also known as the distribution or platform.
Target::DistributionLabel distributionLabel() const
This is shortName and summary attribute of the installed base product.
virtual ~TargetImpl()
Dtor.
bool providesFile(const std::string &path_str, const std::string &name_str) const
If the package is installed and provides the file Needed to evaluate split provides during Resolver::...
HardLocksFile _hardLocksFile
Hard-Locks database.
Pathname root() const
The root set for this target.
void load(bool force=true)
std::string distributionFlavor() const
This is flavor attribute of the installed base product but does not require the target to be loaded a...
void commitInSingleTransaction(const ZYppCommitPolicy &policy_r, CommitPackageCache &packageCache_r, ZYppCommitResult &result_r)
Commit ordered changes (internal helper)
void installSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
ZYppCommitResult commit(ResPool pool_r, const ZYppCommitPolicy &policy_r)
Commit changes in the pool.
VendorAttr _vendorAttr
vendor equivalence settings.
Pathname home() const
The directory to store things.
void commitFindFileConflicts(const ZYppCommitPolicy &policy_r, ZYppCommitResult &result_r)
Commit helper checking for file conflicts after download.
Pathname defaultSolvfilesPath() const
The systems default solv file location.
std::string anonymousUniqueId() const
anonymous unique id
TargetImpl(const Pathname &root_r="/", bool doRebuild_r=false)
Ctor.
bool solvfilesPathIsTemp() const
Whether we're using a temp.
std::string targetDistributionFlavor() const
This is register.flavor attribute of the installed base product.
Interface to the rpm program.
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
void initDatabase(Pathname root_r=Pathname(), bool doRebuild_r=false)
Prepare access to the rpm database below root_r.
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
void closeDatabase()
Block further access to the rpm database and go back to uninitialized state.
bool hasFile(const std::string &file_r, const std::string &name_r="") const
Return true if at least one package owns a certain file (name_r empty) Return true if package name_r ...
Subclass to retrieve database content.
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
bool write(const Pathname &path_r, const std::string &key_r, const std::string &val_r, const std::string &newcomment_r)
Add or change a value in sysconfig file path_r.
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB )
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
int unlink(const Pathname &path)
Like 'unlink'.
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
int assert_file(const Pathname &path, unsigned mode)
Create an empty file if it does not yet exist.
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
int touch(const Pathname &path)
Change file's modification and access times.
std::string md5sum(const Pathname &file)
Compute a files md5sum.
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
BlockingMode setFDBlocking(int fd, bool mode)
std::string getline(std::istream &str)
Read one line from stream.
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
std::string toLower(const std::string &s)
Return lowercase version of s.
unsigned splitEscaped(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t", bool withEmpty=false)
Split line_r into words with respect to escape delimeters.
std::string trim(const std::string &s, const Trim trim_r)
IMPL_PTR_TYPE(TargetImpl)
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
std::string rpmDbStateHash(const Pathname &root_r)
void writeUpgradeTestcase()
static bool fileMissing(const Pathname &pathname)
helper functor
void updateFileContent(const Pathname &filename, boost::function< bool()> condition, boost::function< std::string()> value)
updates the content of filename if condition is true, setting the content the the value returned by v...
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
static std::string generateRandomId()
generates a random id using uuidgen
Easy-to use interface to the ZYPP dependency resolver.
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
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.