libzypp: zypp/target/TargetImpl.cc Source File

libzypp 17.38.6

TargetImpl.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include <iostream>
13#include <fstream>
14#include <sstream>
15#include <string>
16#include <list>
17#include <set>
18
19#include <sys/types.h>
20#include <dirent.h>
21
22#include <zypp-core/base/LogTools.h>
23#include <zypp-core/base/Exception.h>
24#include <zypp-core/base/Iterator.h>
25#include <zypp-core/base/Gettext.h>
26#include <zypp-core/base/IOStream.h>
27#include <zypp-core/base/Functional.h>
28#include <zypp-core/base/UserRequestException>
29#include <zypp/base/Json.h>
30#include <zypp-core/base/Env.h>
31
32#include <zypp/ZConfig.h>
33#include <zypp/ZYppFactory.h>
34#include <zypp/PathInfo.h>
35
36#include <zypp/PoolItem.h>
37#include <zypp/ResObjects.h>
38#include <zypp-core/Url.h>
39#include <zypp/TmpPath.h>
40#include <zypp/RepoStatus.h>
41#include <zypp-core/ExternalProgram.h>
42#include <zypp/Repository.h>
43#include <zypp-core/ShutdownLock_p.h>
44
45#include <zypp/ResFilters.h>
46#include <zypp/HistoryLog.h>
47#include <zypp/target/TargetImpl.h>
48#include <zypp/target/TargetCallbackReceiver.h>
49#include <zypp/target/rpm/librpmDb.h>
50#include <zypp/target/CommitPackageCache.h>
51#include <zypp/target/RpmPostTransCollector.h>
52#include <zypp/target/private/commitpackagepreloader_p.h>
53
54#include <zypp/parser/ProductFileReader.h>
55#include <zypp/repo/SrcPackageProvider.h>
56
57#include <zypp/sat/Pool.h>
58#include <zypp/sat/detail/PoolImpl.h>
59#include <zypp/sat/SolvableSpec.h>
60#include <zypp/sat/Transaction.h>
61
62#include <zypp-core/base/String.h>
63#include <zypp-core/base/StringV.h>
64#include <zypp-core/ng/base/EventLoop>
65#include <zypp-core/ng/base/UnixSignalSource>
66#include <zypp-core/ng/io/AsyncDataSource>
67#include <zypp-core/ng/io/Process>
68#include <zypp-core/base/IOTools.h>
69#include <zypp-core/ng/rpc/stompframestream.h>
70#include <zypp-core/ng/base/private/linuxhelpers_p.h>
71#include <zypp-core/ng/base/EventDispatcher>
72
73#include <shared/commit/CommitMessages.h>
74
75#include <zypp/target/rpm/RpmException.h>
76
77#include <zypp/PluginExecutor.h>
78
79// include the error codes from zypp-rpm
80#include "tools/zypp-rpm/errorcodes.h"
81#include <rpm/rpmlog.h>
82
83#include <optional>
84
85namespace zypp::env {
86 inline bool TRANSACTIONAL_UPDATE()
87 {
88 static bool val = [](){
89 const char * env = getenv("TRANSACTIONAL_UPDATE");
90 return( env && zypp::str::strToBool( env, true ) );
91 }();
92 return val;
93 }
94} // namespace zypp::env
95
96using std::endl;
97
99extern "C"
100{
101#include <solv/repo_rpmdb.h>
102#include <solv/chksum.h>
103}
104namespace zypp
105{
106 namespace target
107 {
108 inline std::string rpmDbStateHash( const Pathname & root_r )
109 {
110 std::string ret;
111 AutoDispose<void*> state { ::rpm_state_create( sat::Pool::instance().get(), root_r.c_str() ), ::rpm_state_free };
112 AutoDispose<Chksum*> chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) -> void {
113 ::solv_chksum_free( chk, nullptr );
114 } };
115 if ( ::rpm_hash_database_state( state, chk ) == 0 )
116 {
117 int md5l;
118 const unsigned char * md5 = ::solv_chksum_get( chk, &md5l );
119 ret = ::pool_bin2hex( sat::Pool::instance().get(), md5, md5l );
120 }
121 else
122 WAR << "rpm_hash_database_state failed" << endl;
123 return ret;
124 }
125
126 inline RepoStatus rpmDbRepoStatus( const Pathname & root_r )
127 { return RepoStatus( rpmDbStateHash( root_r ), Date() ); }
128
129 } // namespace target
130} // namespace
132
134namespace zypp
135{
137 namespace
138 {
139 // HACK for bnc#906096: let pool re-evaluate multiversion spec
140 // if target root changes. ZConfig returns data sensitive to
141 // current target root.
142 inline void sigMultiversionSpecChanged()
143 {
144 if ( sat::detail::PoolMember::poolValid () )
145 sat::detail::PoolMember::myPool().multiversionSpecChanged();
146 }
147 } //namespace
149
151 namespace json
152 {
153 // Lazy via template specialisation / should switch to overloading
154
156 template<>
157 inline json::Value toJSON ( const sat::Transaction::Step & step_r )
158 {
159 static const std::string strType( "type" );
160 static const std::string strStage( "stage" );
161 static const std::string strSolvable( "solvable" );
162
163 static const std::string strTypeDel( "-" );
164 static const std::string strTypeIns( "+" );
165 static const std::string strTypeMul( "M" );
166
167 static const std::string strStageDone( "ok" );
168 static const std::string strStageFailed( "err" );
169
170 static const std::string strSolvableN( "n" );
171 static const std::string strSolvableE( "e" );
172 static const std::string strSolvableV( "v" );
173 static const std::string strSolvableR( "r" );
174 static const std::string strSolvableA( "a" );
175
176 using sat::Transaction;
177 json::Object ret;
178
179 switch ( step_r.stepType() )
180 {
181 case Transaction::TRANSACTION_IGNORE: /*empty*/ break;
182 case Transaction::TRANSACTION_ERASE: ret.add( strType, strTypeDel ); break;
183 case Transaction::TRANSACTION_INSTALL: ret.add( strType, strTypeIns ); break;
184 case Transaction::TRANSACTION_MULTIINSTALL: ret.add( strType, strTypeMul ); break;
185 }
186
187 switch ( step_r.stepStage() )
188 {
189 case Transaction::STEP_TODO: /*empty*/ break;
190 case Transaction::STEP_DONE: ret.add( strStage, strStageDone ); break;
191 case Transaction::STEP_ERROR: ret.add( strStage, strStageFailed ); break;
192 }
193
194 {
195 IdString ident;
196 Edition ed;
197 Arch arch;
198 if ( sat::Solvable solv = step_r.satSolvable() )
199 {
200 ident = solv.ident();
201 ed = solv.edition();
202 arch = solv.arch();
203 }
204 else
205 {
206 // deleted package; post mortem data stored in Transaction::Step
207 ident = step_r.ident();
208 ed = step_r.edition();
209 arch = step_r.arch();
210 }
211
212 json::Object s {
213 { strSolvableN, ident.asString() },
214 { strSolvableV, ed.version() },
215 { strSolvableR, ed.release() },
216 { strSolvableA, arch.asString() }
217 };
218 if ( Edition::epoch_t epoch = ed.epoch() )
219 s.add( strSolvableE, epoch );
220
221 ret.add( strSolvable, s );
222 }
223
224 return ret;
225 }
226
227 template<>
228 inline json::Value toJSON( const ZYppCommitResult::TransactionStepList & steps_r )
229 {
230 using sat::Transaction;
231 json::Array ret;
232
233 for ( const Transaction::Step & step : steps_r )
234 // ignore implicit deletes due to obsoletes and non-package actions
235 if ( step.stepType() != Transaction::TRANSACTION_IGNORE )
236 ret.add( toJSON(step) );
237
238 return ret;
239 }
240
241 } // namespace json
242
243
245 namespace target
246 {
248 namespace
249 {
250 struct InstallResolvableSAReportReceiver : public callback::ReceiveReport<rpm::InstallResolvableReportSA>
251 {
252 using ReportType = callback::SendReport<rpm::InstallResolvableReport>;
253
254 InstallResolvableSAReportReceiver()
255 : _report { std::make_unique<ReportType>() }
256 {}
257
258 void start( Resolvable::constPtr resolvable, const UserData & = UserData() /*userdata*/ ) override
259 { (*_report)->start( resolvable ); }
260
261 void progress( int value, Resolvable::constPtr resolvable, const UserData & = UserData() /*userdata*/ ) override
262 { (*_report)->progress( value, resolvable ); }
263
264 void finish( Resolvable::constPtr resolvable, Error error, const UserData & = UserData() /*userdata*/ ) override
265 { (*_report)->finish( resolvable, static_cast<rpm::InstallResolvableReport::Error>(error), "", rpm::InstallResolvableReport::RpmLevel::RPM/*unused legacy*/ ); }
266
267 private:
268 std::unique_ptr<ReportType> _report;
269 };
270
271 struct RemoveResolvableSAReportReceiver : public callback::ReceiveReport<rpm::RemoveResolvableReportSA>
272 {
273 using ReportType = callback::SendReport<rpm::RemoveResolvableReport>;
274
275 RemoveResolvableSAReportReceiver()
276 : _report { std::make_unique<ReportType>() }
277 {}
278
279 virtual void start( Resolvable::constPtr resolvable, const UserData & = UserData() /*userdata*/ )
280 { (*_report)->start( resolvable ); }
281
282 virtual void progress( int value, Resolvable::constPtr resolvable, const UserData & = UserData() /*userdata*/ )
283 { (*_report)->progress( value, resolvable ); }
284
285 virtual void finish( Resolvable::constPtr resolvable, Error error, const UserData & = UserData() /*userdata*/ )
286 { (*_report)->finish( resolvable, static_cast<rpm::RemoveResolvableReport::Error>(error), "" ); }
287
288 private:
289 std::unique_ptr<ReportType> _report;
290 };
291
297 struct SingleTransReportLegacyWrapper
298 {
299 NON_COPYABLE(SingleTransReportLegacyWrapper);
300 NON_MOVABLE(SingleTransReportLegacyWrapper);
301
302 SingleTransReportLegacyWrapper()
303 {
304 if ( not singleTransReportsConnected() and legacyReportsConnected() )
305 {
306 WAR << "Activating SingleTransReportLegacyWrapper! The application does not listen to the singletrans reports :(" << endl;
307 _installResolvableSAReportReceiver = InstallResolvableSAReportReceiver();
308 _removeResolvableSAReportReceiver = RemoveResolvableSAReportReceiver();
309 _installResolvableSAReportReceiver->connect();
310 _removeResolvableSAReportReceiver->connect();
311
312 }
313 }
314
315 ~SingleTransReportLegacyWrapper()
316 {
317 }
318
319 bool singleTransReportsConnected() const
320 {
321 return callback::SendReport<rpm::SingleTransReport>::connected()
322 || callback::SendReport<rpm::InstallResolvableReportSA>::connected()
323 || callback::SendReport<rpm::RemoveResolvableReportSA>::connected()
324 || callback::SendReport<rpm::CommitScriptReportSA>::connected()
325 || callback::SendReport<rpm::TransactionReportSA>::connected()
326 || callback::SendReport<rpm::CleanupPackageReportSA>::connected()
327 ;
328 }
329
330 bool legacyReportsConnected() const
331 {
332 return callback::SendReport<rpm::InstallResolvableReport>::connected()
333 || callback::SendReport<rpm::RemoveResolvableReport>::connected()
334 ;
335 }
336
337 private:
338 std::optional<InstallResolvableSAReportReceiver> _installResolvableSAReportReceiver;
339 std::optional<RemoveResolvableSAReportReceiver> _removeResolvableSAReportReceiver;
340 };
341 } //namespace
343
345 namespace
346 {
347 class AssertMountedBase
348 {
349 NON_COPYABLE(AssertMountedBase);
350 NON_MOVABLE(AssertMountedBase);
351 protected:
352 AssertMountedBase()
353 {}
354
355 ~AssertMountedBase()
356 {
357 if ( ! _mountpoint.empty() ) {
358 // we mounted it so we unmount...
359 MIL << "We mounted " << _mountpoint << " so we unmount it" << endl;
360 execute({ "umount", "-R", "-l", _mountpoint.asString() });
361 }
362 }
363
364 protected:
365 int execute( ExternalProgram::Arguments && cmd_r ) const
366 {
367 ExternalProgram prog( cmd_r, ExternalProgram::Stderr_To_Stdout );
368 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
369 { DBG << line; }
370 return prog.close();
371 }
372
373 protected:
374 Pathname _mountpoint;
375
376 };
377
380 class AssertProcMounted : private AssertMountedBase
381 {
382 public:
383 AssertProcMounted( Pathname root_r )
384 {
385 root_r /= "/proc";
386 if ( ! PathInfo(root_r/"self").isDir() ) {
387 MIL << "Try to make sure proc is mounted at" << root_r << endl;
388 if ( filesystem::assert_dir(root_r) == 0
389 && execute({ "mount", "-t", "proc", "/proc", root_r.asString() }) == 0 ) {
390 _mountpoint = std::move(root_r); // so we'll later unmount it
391 }
392 else {
393 WAR << "Mounting proc at " << root_r << " failed" << endl;
394 }
395 }
396 }
397 };
398
401 class AssertDevMounted : private AssertMountedBase
402 {
403 public:
404 AssertDevMounted( Pathname root_r )
405 {
406 root_r /= "/dev";
407 if ( ! PathInfo(root_r/"null").isChr() ) {
408 MIL << "Try to make sure dev is mounted at" << root_r << endl;
409 // https://unix.stackexchange.com/questions/263972/unmount-a-rbind-mount-without-affecting-the-original-mount
410 // Without --make-rslave unmounting <sandbox-root>/dev/pts
411 // may unmount /dev/pts and you're out of ptys.
412 if ( filesystem::assert_dir(root_r) == 0
413 && execute({ "mount", "--rbind", "--make-rslave", "/dev", root_r.asString() }) == 0 ) {
414 _mountpoint = std::move(root_r); // so we'll later unmount it
415 }
416 else {
417 WAR << "Mounting dev at " << root_r << " failed" << endl;
418 }
419 }
420 }
421 };
422
423 } // namespace
425
427 namespace
428 {
429 SolvIdentFile::Data getUserInstalledFromHistory( const Pathname & historyFile_r )
430 {
431 SolvIdentFile::Data onSystemByUserList;
432 // go and parse it: 'who' must constain an '@', then it was installed by user request.
433 // 2009-09-29 07:25:19|install|lirc-remotes|0.8.5-3.2|x86_64|root@opensuse|InstallationImage|a204211eb0...
434 std::ifstream infile( historyFile_r.c_str() );
435 for( iostr::EachLine in( infile ); in; in.next() )
436 {
437 const char * ch( (*in).c_str() );
438 // start with year
439 if ( *ch < '1' || '9' < *ch )
440 continue;
441 const char * sep1 = ::strchr( ch, '|' ); // | after date
442 if ( !sep1 )
443 continue;
444 ++sep1;
445 // if logs an install or delete
446 bool installs = true;
447 if ( ::strncmp( sep1, "install|", 8 ) )
448 {
449 if ( ::strncmp( sep1, "remove |", 8 ) )
450 continue; // no install and no remove
451 else
452 installs = false; // remove
453 }
454 sep1 += 8; // | after what
455 // get the package name
456 const char * sep2 = ::strchr( sep1, '|' ); // | after name
457 if ( !sep2 || sep1 == sep2 )
458 continue;
459 (*in)[sep2-ch] = '\0';
460 IdString pkg( sep1 );
461 // we're done, if a delete
462 if ( !installs )
463 {
464 onSystemByUserList.erase( pkg );
465 continue;
466 }
467 // now guess whether user installed or not (3rd next field contains 'user@host')
468 if ( (sep1 = ::strchr( sep2+1, '|' )) // | after version
469 && (sep1 = ::strchr( sep1+1, '|' )) // | after arch
470 && (sep2 = ::strchr( sep1+1, '|' )) ) // | after who
471 {
472 (*in)[sep2-ch] = '\0';
473 if ( ::strchr( sep1+1, '@' ) )
474 {
475 // by user
476 onSystemByUserList.insert( pkg );
477 continue;
478 }
479 }
480 }
481 MIL << "onSystemByUserList found: " << onSystemByUserList.size() << endl;
482 return onSystemByUserList;
483 }
484 } // namespace
486
488 namespace
489 {
490 inline PluginFrame transactionPluginFrame( const std::string & command_r, const ZYppCommitResult::TransactionStepList & steps_r )
491 {
492 return PluginFrame( command_r, json::Object {
493 { "TransactionStepList", json::toJSON(steps_r) }
494 }.asJSON() );
495 }
496 } // namespace
498
500 void writeUpgradeTestcase()
501 {
502 unsigned toKeep( ZConfig::instance().solver_upgradeTestcasesToKeep() );
503 MIL << "Testcases to keep: " << toKeep << endl;
504 if ( !toKeep )
505 return;
506 Target_Ptr target( getZYpp()->getTarget() );
507 if ( ! target )
508 {
509 WAR << "No Target no Testcase!" << endl;
510 return;
511 }
512
513 std::string stem( "updateTestcase" );
514 Pathname dir( target->assertRootPrefix("/var/log/") );
515 Pathname next( dir / Date::now().form( stem+"-%Y-%m-%d-%H-%M-%S" ) );
516
517 {
518 std::list<std::string> content;
519 filesystem::readdir( content, dir, /*dots*/false );
520 std::set<std::string> cases;
521 for_( c, content.begin(), content.end() )
522 {
523 if ( str::startsWith( *c, stem ) )
524 cases.insert( *c );
525 }
526 if ( cases.size() >= toKeep )
527 {
528 unsigned toDel = cases.size() - toKeep + 1; // +1 for the new one
529 for_( c, cases.begin(), cases.end() )
530 {
531 filesystem::recursive_rmdir( dir/(*c) );
532 if ( ! --toDel )
533 break;
534 }
535 }
536 }
537
538 MIL << "Write new testcase " << next << endl;
539 getZYpp()->resolver()->createSolverTestcase( next.asString(), false/*no solving*/ );
540 }
541
543 namespace
544 {
545
556 std::pair<bool,PatchScriptReport::Action> doExecuteScript( const Pathname & root_r,
557 const Pathname & script_r,
558 callback::SendReport<PatchScriptReport> & report_r )
559 {
560 MIL << "Execute script " << PathInfo(Pathname::assertprefix( root_r,script_r)) << endl;
561
562 HistoryLog historylog;
563 historylog.comment(script_r.asString() + _(" executed"), /*timestamp*/true);
564 ExternalProgram prog( script_r.asString(), ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r );
565
566 for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() )
567 {
568 historylog.comment(output);
569 if ( ! report_r->progress( PatchScriptReport::OUTPUT, output ) )
570 {
571 WAR << "User request to abort script " << script_r << endl;
572 prog.kill();
573 // the rest is handled by exit code evaluation
574 // in case the script has meanwhile finished.
575 }
576 }
577
578 std::pair<bool,PatchScriptReport::Action> ret( std::make_pair( false, PatchScriptReport::ABORT ) );
579
580 if ( prog.close() != 0 )
581 {
582 ret.second = report_r->problem( prog.execError() );
583 WAR << "ACTION" << ret.second << "(" << prog.execError() << ")" << endl;
584 std::ostringstream sstr;
585 sstr << script_r << _(" execution failed") << " (" << prog.execError() << ")" << endl;
586 historylog.comment(sstr.str(), /*timestamp*/true);
587 return ret;
588 }
589
590 report_r->finish();
591 ret.first = true;
592 return ret;
593 }
594
598 bool executeScript( const Pathname & root_r,
599 const Pathname & script_r,
600 callback::SendReport<PatchScriptReport> & report_r )
601 {
602 std::pair<bool,PatchScriptReport::Action> action( std::make_pair( false, PatchScriptReport::ABORT ) );
603
604 do {
605 action = doExecuteScript( root_r, script_r, report_r );
606 if ( action.first )
607 return true; // success
608
609 switch ( action.second )
610 {
611 case PatchScriptReport::ABORT:
612 WAR << "User request to abort at script " << script_r << endl;
613 return false; // requested abort.
614 break;
615
616 case PatchScriptReport::IGNORE:
617 WAR << "User request to skip script " << script_r << endl;
618 return true; // requested skip.
619 break;
620
621 case PatchScriptReport::RETRY:
622 break; // again
623 }
624 } while ( action.second == PatchScriptReport::RETRY );
625
626 // THIS is not intended to be reached:
627 INT << "Abort on unknown ACTION request " << action.second << " returned" << endl;
628 return false; // abort.
629 }
630
636 bool RunUpdateScripts( const Pathname & root_r,
637 const Pathname & scriptsPath_r,
638 const std::vector<sat::Solvable> & checkPackages_r,
639 bool aborting_r )
640 {
641 if ( checkPackages_r.empty() )
642 return true; // no installed packages to check
643
644 MIL << "Looking for new update scripts in (" << root_r << ")" << scriptsPath_r << endl;
645 Pathname scriptsDir( Pathname::assertprefix( root_r, scriptsPath_r ) );
646 if ( ! PathInfo( scriptsDir ).isDir() )
647 return true; // no script dir
648
649 std::list<std::string> scripts;
650 filesystem::readdir( scripts, scriptsDir, /*dots*/false );
651 if ( scripts.empty() )
652 return true; // no scripts in script dir
653
654 // Now collect and execute all matching scripts.
655 // On ABORT: at least log all outstanding scripts.
656 // - "name-version-release"
657 // - "name-version-release-*"
658 bool abort = false;
659 std::map<std::string, Pathname> unify; // scripts <md5,path>
660 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
661 {
662 std::string prefix( str::form( "%s-%s", it->name().c_str(), it->edition().c_str() ) );
663 for_( sit, scripts.begin(), scripts.end() )
664 {
665 if ( ! str::hasPrefix( *sit, prefix ) )
666 continue;
667
668 if ( (*sit)[prefix.size()] != '\0' && (*sit)[prefix.size()] != '-' )
669 continue; // if not exact match it had to continue with '-'
670
671 PathInfo script( scriptsDir / *sit );
672 Pathname localPath( scriptsPath_r/(*sit) ); // without root prefix
673 std::string unifytag; // must not stay empty
674
675 if ( script.isFile() )
676 {
677 // Assert it's set as executable, unify by md5sum.
678 filesystem::addmod( script.path(), 0500 );
679 unifytag = filesystem::md5sum( script.path() );
680 }
681 else if ( ! script.isExist() )
682 {
683 // Might be a dangling symlink, might be ok if we are in
684 // instsys (absolute symlink within the system below /mnt).
685 // readlink will tell....
686 unifytag = filesystem::readlink( script.path() ).asString();
687 }
688
689 if ( unifytag.empty() )
690 continue;
691
692 // Unify scripts
693 if ( unify[unifytag].empty() )
694 {
695 unify[unifytag] = localPath;
696 }
697 else
698 {
699 // translators: We may find the same script content in files with different names.
700 // Only the first occurence is executed, subsequent ones are skipped. It's a one-line
701 // message for a log file. Preferably start translation with "%s"
702 std::string msg( str::form(_("%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) );
703 MIL << "Skip update script: " << msg << endl;
704 HistoryLog().comment( msg, /*timestamp*/true );
705 continue;
706 }
707
708 if ( abort || aborting_r )
709 {
710 WAR << "Aborting: Skip update script " << *sit << endl;
711 HistoryLog().comment(
712 localPath.asString() + _(" execution skipped while aborting"),
713 /*timestamp*/true);
714 }
715 else
716 {
717 MIL << "Found update script " << *sit << endl;
718 callback::SendReport<PatchScriptReport> report;
719 report->start( make<Package>( *it ), script.path() );
720
721 if ( ! executeScript( root_r, localPath, report ) ) // script path without root prefix!
722 abort = true; // requested abort.
723 }
724 }
725 }
726 return !abort;
727 }
728
730 //
732
733 inline void copyTo( std::ostream & out_r, const Pathname & file_r )
734 {
735 std::ifstream infile( file_r.c_str() );
736 for( iostr::EachLine in( infile ); in; in.next() )
737 {
738 out_r << *in << endl;
739 }
740 }
741
742 inline std::string notificationCmdSubst( const std::string & cmd_r, const UpdateNotificationFile & notification_r )
743 {
744 std::string ret( cmd_r );
745#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL )
746 SUBST_IF( "%p", notification_r.solvable().asString() );
747 SUBST_IF( "%P", notification_r.file().asString() );
748#undef SUBST_IF
749 return ret;
750 }
751
752 void sendNotification( const Pathname & root_r,
753 const UpdateNotifications & notifications_r )
754 {
755 if ( notifications_r.empty() )
756 return;
757
758 std::string cmdspec( ZConfig::instance().updateMessagesNotify() );
759 MIL << "Notification command is '" << cmdspec << "'" << endl;
760 if ( cmdspec.empty() )
761 return;
762
763 std::string::size_type pos( cmdspec.find( '|' ) );
764 if ( pos == std::string::npos )
765 {
766 ERR << "Can't send Notification: Missing 'format |' in command spec." << endl;
767 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
768 return;
769 }
770
771 std::string formatStr( str::toLower( str::trim( cmdspec.substr( 0, pos ) ) ) );
772 std::string commandStr( str::trim( cmdspec.substr( pos + 1 ) ) );
773
774 enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK };
775 Format format = UNKNOWN;
776 if ( formatStr == "none" )
777 format = NONE;
778 else if ( formatStr == "single" )
779 format = SINGLE;
780 else if ( formatStr == "digest" )
781 format = DIGEST;
782 else if ( formatStr == "bulk" )
783 format = BULK;
784 else
785 {
786 ERR << "Can't send Notification: Unknown format '" << formatStr << " |' in command spec." << endl;
787 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
788 return;
789 }
790
791 // Take care: commands are ececuted chroot(root_r). The message file
792 // pathnames in notifications_r are local to root_r. For physical access
793 // to the file they need to be prefixed.
794
795 if ( format == NONE || format == SINGLE )
796 {
797 for_( it, notifications_r.begin(), notifications_r.end() )
798 {
799 std::vector<std::string> command;
800 if ( format == SINGLE )
801 command.push_back( "<"+Pathname::assertprefix( root_r, it->file() ).asString() );
802 str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) );
803
804 ExternalProgram prog( command, ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r );
805 if ( true ) // Wait for feedback
806 {
807 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
808 {
809 DBG << line;
810 }
811 int ret = prog.close();
812 if ( ret != 0 )
813 {
814 ERR << "Notification command returned with error (" << ret << ")." << endl;
815 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
816 return;
817 }
818 }
819 }
820 }
821 else if ( format == DIGEST || format == BULK )
822 {
823 filesystem::TmpFile tmpfile;
824 std::ofstream out( tmpfile.path().c_str() );
825 for_( it, notifications_r.begin(), notifications_r.end() )
826 {
827 if ( format == DIGEST )
828 {
829 out << it->file() << endl;
830 }
831 else if ( format == BULK )
832 {
833 copyTo( out << '\f', Pathname::assertprefix( root_r, it->file() ) );
834 }
835 }
836
837 std::vector<std::string> command;
838 command.push_back( "<"+tmpfile.path().asString() ); // redirect input
839 str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) );
840
841 ExternalProgram prog( command, ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r );
842 if ( true ) // Wait for feedback otherwise the TmpFile goes out of scope.
843 {
844 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
845 {
846 DBG << line;
847 }
848 int ret = prog.close();
849 if ( ret != 0 )
850 {
851 ERR << "Notification command returned with error (" << ret << ")." << endl;
852 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
853 return;
854 }
855 }
856 }
857 else
858 {
859 INT << "Can't send Notification: Missing handler for 'format |' in command spec." << endl;
860 HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true );
861 return;
862 }
863 }
864
865
871 void RunUpdateMessages( const Pathname & root_r,
872 const Pathname & messagesPath_r,
873 const std::vector<sat::Solvable> & checkPackages_r,
874 ZYppCommitResult & result_r )
875 {
876 if ( checkPackages_r.empty() )
877 return; // no installed packages to check
878
879 MIL << "Looking for new update messages in (" << root_r << ")" << messagesPath_r << endl;
880 Pathname messagesDir( Pathname::assertprefix( root_r, messagesPath_r ) );
881 if ( ! PathInfo( messagesDir ).isDir() )
882 return; // no messages dir
883
884 std::list<std::string> messages;
885 filesystem::readdir( messages, messagesDir, /*dots*/false );
886 if ( messages.empty() )
887 return; // no messages in message dir
888
889 // Now collect all matching messages in result and send them
890 // - "name-version-release"
891 // - "name-version-release-*"
892 HistoryLog historylog;
893 for_( it, checkPackages_r.begin(), checkPackages_r.end() )
894 {
895 std::string prefix( str::form( "%s-%s", it->name().c_str(), it->edition().c_str() ) );
896 for_( sit, messages.begin(), messages.end() )
897 {
898 if ( ! str::hasPrefix( *sit, prefix ) )
899 continue;
900
901 if ( (*sit)[prefix.size()] != '\0' && (*sit)[prefix.size()] != '-' )
902 continue; // if not exact match it had to continue with '-'
903
904 PathInfo message( messagesDir / *sit );
905 if ( ! message.isFile() || message.size() == 0 )
906 continue;
907
908 MIL << "Found update message " << *sit << endl;
909 Pathname localPath( messagesPath_r/(*sit) ); // without root prefix
910 result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) );
911 historylog.comment( str::Str() << _("New update message") << " " << localPath, /*timestamp*/true );
912 }
913 }
914 sendNotification( root_r, result_r.updateMessages() );
915 }
916
920 void logPatchStatusChanges( const sat::Transaction & transaction_r, TargetImpl & target_r )
921 {
922 ResPool::ChangedPseudoInstalled changedPseudoInstalled { ResPool::instance().changedPseudoInstalled() };
923 if ( changedPseudoInstalled.empty() )
924 return;
925
926 if ( ! transaction_r.actionEmpty( ~sat::Transaction::STEP_DONE ) )
927 {
928 // Need to recompute the patch list if commit is incomplete!
929 // We remember the initially established status, then reload the
930 // Target to get the current patch status. Then compare.
931 WAR << "Need to recompute the patch status changes as commit is incomplete!" << endl;
932 ResPool::EstablishedStates establishedStates{ ResPool::instance().establishedStates() };
933 target_r.load();
934 changedPseudoInstalled = establishedStates.changedPseudoInstalled();
935 }
936
937 HistoryLog historylog;
938 for ( const auto & el : changedPseudoInstalled )
939 historylog.patchStateChange( el.first, el.second );
940 }
941
943 } // namespace
945
946 void XRunUpdateMessages( const Pathname & root_r,
947 const Pathname & messagesPath_r,
948 const std::vector<sat::Solvable> & checkPackages_r,
949 ZYppCommitResult & result_r )
950 { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); }
951
953
954 IMPL_PTR_TYPE(TargetImpl);
955
957 //
958 // METHOD NAME : TargetImpl::TargetImpl
959 // METHOD TYPE : Ctor
960 //
961 TargetImpl::TargetImpl( const Pathname & root_r, bool doRebuild_r )
962 : _root( root_r )
963 , _requestedLocalesFile( home() / "RequestedLocales" )
964 , _autoInstalledFile( home() / "AutoInstalled" )
965 , _hardLocksFile( Pathname::assertprefix( _root, ZConfig::instance().locksFile() ) )
966 , _vendorAttr( Pathname::assertprefix( _root, ZConfig::instance().vendorPath() ) )
967 {
968 _rpm.initDatabase( root_r, doRebuild_r );
969
970 HistoryLog::setRoot(_root);
971
972 createAnonymousId();
973 sigMultiversionSpecChanged(); // HACK: see sigMultiversionSpecChanged
974 MIL << "Initialized target on " << _root << endl;
975 }
976
980 static std::string generateRandomId()
981 {
982 std::ifstream uuidprovider( "/proc/sys/kernel/random/uuid" );
983 return iostr::getline( uuidprovider );
984 }
985
991 void updateFileContent( const Pathname &filename,
992 boost::function<bool ()> condition,
993 boost::function<std::string ()> value )
994 {
995 std::string val = value();
996 // if the value is empty, then just dont
997 // do anything, regardless of the condition
998 if ( val.empty() )
999 return;
1000
1001 if ( condition() )
1002 {
1003 MIL << "updating '" << filename << "' content." << endl;
1004
1005 // if the file does not exist we need to generate the uuid file
1006
1007 std::ofstream filestr;
1008 // make sure the path exists
1009 filesystem::assert_dir( filename.dirname() );
1010 filestr.open( filename.c_str() );
1011
1012 if ( filestr.good() )
1013 {
1014 filestr << val;
1015 filestr.close();
1016 }
1017 else
1018 {
1019 // FIXME, should we ignore the error?
1020 ZYPP_THROW(Exception("Can't openfile '" + filename.asString() + "' for writing"));
1021 }
1022 }
1023 }
1024
1026 static bool fileMissing( const Pathname &pathname )
1027 {
1028 return ! PathInfo(pathname).isExist();
1029 }
1030
1031 void TargetImpl::createAnonymousId() const
1032 {
1033 // bsc#1024741: Omit creating a new uid for chrooted systems (if it already has one, fine)
1034 if ( root() != "/" )
1035 return;
1036
1037 // Create the anonymous unique id, used for download statistics
1038 Pathname idpath( home() / "AnonymousUniqueId");
1039
1040 try
1041 {
1042 updateFileContent( idpath,
1043 std::bind(fileMissing, idpath),
1044 generateRandomId );
1045 }
1046 catch ( const Exception &e )
1047 {
1048 WAR << "Can't create anonymous id file" << endl;
1049 }
1050
1051 }
1052
1053 void TargetImpl::createLastDistributionFlavorCache() const
1054 {
1055 // create the anonymous unique id
1056 // this value is used for statistics
1057 Pathname flavorpath( home() / "LastDistributionFlavor");
1058
1059 // is there a product
1060 Product::constPtr p = baseProduct();
1061 if ( ! p )
1062 {
1063 WAR << "No base product, I won't create flavor cache" << endl;
1064 return;
1065 }
1066
1067 std::string flavor = p->flavor();
1068
1069 try
1070 {
1071
1072 updateFileContent( flavorpath,
1073 // only if flavor is not empty
1074 functor::Constant<bool>( ! flavor.empty() ),
1075 functor::Constant<std::string>(flavor) );
1076 }
1077 catch ( const Exception &e )
1078 {
1079 WAR << "Can't create flavor cache" << endl;
1080 return;
1081 }
1082 }
1083
1085 //
1086 // METHOD NAME : TargetImpl::~TargetImpl
1087 // METHOD TYPE : Dtor
1088 //
1089 TargetImpl::~TargetImpl()
1090 {
1091 _rpm.closeDatabase();
1092 sigMultiversionSpecChanged(); // HACK: see sigMultiversionSpecChanged
1093 MIL << "Closed target on " << _root << endl;
1094 }
1095
1097 //
1098 // solv file handling
1099 //
1101
1102 Pathname TargetImpl::defaultSolvfilesPath() const
1103 {
1104 return Pathname::assertprefix( _root, ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoAlias() );
1105 }
1106
1107 void TargetImpl::clearCache()
1108 {
1109 Pathname base = solvfilesPath();
1110 filesystem::recursive_rmdir( base );
1111 }
1112
1113 bool TargetImpl::buildCache()
1114 {
1115 Pathname base = solvfilesPath();
1116 Pathname rpmsolv = base/"solv";
1117 Pathname rpmsolvcookie = base/"cookie";
1118
1119 bool build_rpm_solv = true;
1120 // lets see if the rpm solv cache exists
1121
1122 RepoStatus rpmstatus( rpmDbRepoStatus(_root) && RepoStatus(_root/"etc/products.d") );
1123
1124 bool solvexisted = PathInfo(rpmsolv).isExist();
1125 if ( solvexisted )
1126 {
1127 // see the status of the cache
1128 PathInfo cookie( rpmsolvcookie );
1129 MIL << "Read cookie: " << cookie << endl;
1130 if ( cookie.isExist() )
1131 {
1132 RepoStatus status = RepoStatus::fromCookieFile(rpmsolvcookie);
1133 // now compare it with the rpm database
1134 if ( status == rpmstatus )
1135 build_rpm_solv = false;
1136 MIL << "Read cookie: " << rpmsolvcookie << " says: "
1137 << (build_rpm_solv ? "outdated" : "uptodate") << endl;
1138 }
1139 }
1140
1141 if ( build_rpm_solv )
1142 {
1143 // if the solvfile dir does not exist yet, we better create it
1144 filesystem::assert_dir( base );
1145
1146 Pathname oldSolvFile( solvexisted ? rpmsolv : Pathname() ); // to speedup rpmdb2solv
1147
1148 filesystem::TmpFile tmpsolv( filesystem::TmpFile::makeSibling( rpmsolv ) );
1149 if ( !tmpsolv )
1150 {
1151 // Can't create temporary solv file, usually due to insufficient permission
1152 // (user query while @System solv needs refresh). If so, try switching
1153 // to a location within zypps temp. space (will be cleaned at application end).
1154
1155 bool switchingToTmpSolvfile = false;
1156 Exception ex("Failed to cache rpm database.");
1157 ex.remember(str::form("Cannot create temporary file under %s.", base.c_str()));
1158
1159 if ( ! solvfilesPathIsTemp() )
1160 {
1161 base = getZYpp()->tmpPath() / sat::Pool::instance().systemRepoAlias();
1162 rpmsolv = base/"solv";
1163 rpmsolvcookie = base/"cookie";
1164
1165 filesystem::assert_dir( base );
1166 tmpsolv = filesystem::TmpFile::makeSibling( rpmsolv );
1167
1168 if ( tmpsolv )
1169 {
1170 WAR << "Using a temporary solv file at " << base << endl;
1171 switchingToTmpSolvfile = true;
1172 _tmpSolvfilesPath = base;
1173 }
1174 else
1175 {
1176 ex.remember(str::form("Cannot create temporary file under %s.", base.c_str()));
1177 }
1178 }
1179
1180 if ( ! switchingToTmpSolvfile )
1181 {
1182 ZYPP_THROW(ex);
1183 }
1184 }
1185
1186 // Take care we unlink the solvfile on exception
1187 ManagedFile guard( base, filesystem::recursive_rmdir );
1188
1189 ExternalProgram::Arguments cmd;
1190#ifdef ZYPP_RPMDB2SOLV_PATH
1191 cmd.push_back( ZYPP_RPMDB2SOLV_PATH );
1192#else
1193 cmd.push_back( "rpmdb2solv" );
1194#endif
1195 if ( ! _root.empty() ) {
1196 cmd.push_back( "-r" );
1197 cmd.push_back( _root.asString() );
1198 }
1199 cmd.push_back( "-D" );
1200 cmd.push_back( rpm().dbPath().asString() );
1201 cmd.push_back( "-X" ); // autogenerate pattern/product/... from -package
1202 // bsc#1104415: no more application support // cmd.push_back( "-A" ); // autogenerate application pseudo packages
1203 cmd.push_back( "-p" );
1204 cmd.push_back( Pathname::assertprefix( _root, "/etc/products.d" ).asString() );
1205
1206 if ( ! oldSolvFile.empty() )
1207 cmd.push_back( oldSolvFile.asString() );
1208
1209 cmd.push_back( "-o" );
1210 cmd.push_back( tmpsolv.path().asString() );
1211
1212 ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout );
1213 std::string errdetail;
1214
1215 for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
1216 WAR << " " << output;
1217 if ( errdetail.empty() ) {
1218 errdetail = prog.command();
1219 errdetail += '\n';
1220 }
1221 errdetail += output;
1222 }
1223
1224 int ret = prog.close();
1225 if ( ret != 0 )
1226 {
1227 Exception ex(str::form("Failed to cache rpm database (%d).", ret));
1228 ex.remember( errdetail );
1229 ZYPP_THROW(ex);
1230 }
1231
1232 ret = filesystem::rename( tmpsolv, rpmsolv );
1233 if ( ret != 0 )
1234 ZYPP_THROW(Exception("Failed to move cache to final destination"));
1235 // if this fails, don't bother throwing exceptions
1236 filesystem::chmod( rpmsolv, 0644 );
1237
1238 rpmstatus.saveToCookieFile(rpmsolvcookie);
1239
1240 // We keep it.
1241 guard.resetDispose();
1242 sat::updateSolvFileIndex( rpmsolv ); // content digest for zypper bash completion
1243
1244 // system-hook: Finally send notification to plugins
1245 if ( root() == "/" )
1246 {
1247 PluginExecutor plugins;
1248 plugins.load( ZConfig::instance().pluginsPath()/"system" );
1249 if ( plugins )
1250 plugins.send( PluginFrame( "PACKAGESETCHANGED" ) );
1251 }
1252 }
1253 else
1254 {
1255 // On the fly add missing solv.idx files for bash completion.
1256 if ( ! PathInfo(base/"solv.idx").isExist() )
1257 sat::updateSolvFileIndex( rpmsolv );
1258 }
1259 return build_rpm_solv;
1260 }
1261
1262 void TargetImpl::reload()
1263 {
1264 load( false );
1265 }
1266
1267 void TargetImpl::unload()
1268 {
1269 Repository system( sat::Pool::instance().findSystemRepo() );
1270 if ( system )
1271 system.eraseFromPool();
1272 }
1273
1274 void TargetImpl::load( bool force )
1275 {
1276 bool newCache = buildCache();
1277 MIL << "New cache built: " << (newCache?"true":"false") <<
1278 ", force loading: " << (force?"true":"false") << endl;
1279
1280 // now add the repos to the pool
1281 sat::Pool satpool( sat::Pool::instance() );
1282 Pathname rpmsolv( solvfilesPath() / "solv" );
1283 MIL << "adding " << rpmsolv << " to pool(" << satpool.systemRepoAlias() << ")" << endl;
1284
1285 // Providing an empty system repo, unload any old content
1286 Repository system( sat::Pool::instance().findSystemRepo() );
1287
1288 if ( system && ! system.solvablesEmpty() )
1289 {
1290 if ( newCache || force )
1291 {
1292 system.eraseFromPool(); // invalidates system
1293 }
1294 else
1295 {
1296 return; // nothing to do
1297 }
1298 }
1299
1300 if ( ! system )
1301 {
1302 system = satpool.systemRepo();
1303 }
1304
1305 try
1306 {
1307 MIL << "adding " << rpmsolv << " to system" << endl;
1308 system.addSolv( rpmsolv );
1309 }
1310 catch ( const Exception & exp )
1311 {
1312 ZYPP_CAUGHT( exp );
1313 MIL << "Try to handle exception by rebuilding the solv-file" << endl;
1314 clearCache();
1315 buildCache();
1316
1317 system.addSolv( rpmsolv );
1318 }
1319 satpool.rootDir( _root );
1320
1321 // (Re)Load the requested locales et al.
1322 // If the requested locales are empty, we leave the pool untouched
1323 // to avoid undoing changes the application applied. We expect this
1324 // to happen on a bare metal installation only. An already existing
1325 // target should be loaded before its settings are changed.
1326 {
1327 const LocaleSet & requestedLocales( _requestedLocalesFile.locales() );
1328 if ( ! requestedLocales.empty() )
1329 {
1330 satpool.initRequestedLocales( requestedLocales );
1331 }
1332 }
1333 {
1334 if ( ! PathInfo( _autoInstalledFile.file() ).isExist() )
1335 {
1336 // Initialize from history, if it does not exist
1337 Pathname historyFile( Pathname::assertprefix( _root, ZConfig::instance().historyLogFile() ) );
1338 if ( PathInfo( historyFile ).isExist() )
1339 {
1340 SolvIdentFile::Data onSystemByUser( getUserInstalledFromHistory( historyFile ) );
1341 SolvIdentFile::Data onSystemByAuto;
1342 for_( it, system.solvablesBegin(), system.solvablesEnd() )
1343 {
1344 IdString ident( (*it).ident() );
1345 if ( onSystemByUser.find( ident ) == onSystemByUser.end() )
1346 onSystemByAuto.insert( ident );
1347 }
1348 _autoInstalledFile.setData( onSystemByAuto );
1349 }
1350 // on the fly removed any obsolete SoftLocks file
1351 filesystem::unlink( home() / "SoftLocks" );
1352 }
1353 // read from AutoInstalled file
1354 sat::StringQueue q;
1355 for ( const auto & idstr : _autoInstalledFile.data() )
1356 q.push( idstr.id() );
1357 satpool.setAutoInstalled( q );
1358 }
1359
1360 // Load the needreboot package specs
1361 {
1362 sat::SolvableSpec needrebootSpec;
1363 needrebootSpec.addProvides( Capability("installhint(reboot-needed)") );
1364 needrebootSpec.addProvides( Capability("kernel") );
1365
1366 Pathname needrebootFile { Pathname::assertprefix( root(), ZConfig::instance().needrebootFile() ) };
1367 if ( PathInfo( needrebootFile ).isFile() )
1368 needrebootSpec.parseFrom( needrebootFile );
1369
1370 Pathname needrebootDir { Pathname::assertprefix( root(), ZConfig::instance().needrebootPath() ) };
1371 if ( PathInfo( needrebootDir ).isDir() )
1372 {
1373 static const StrMatcher isRpmConfigBackup( "\\.rpm(new|save|orig)$", Match::REGEX );
1374
1375 filesystem::dirForEach( needrebootDir, filesystem::matchNoDots(),
1376 [&]( const Pathname & dir_r, const char *const str_r )->bool
1377 {
1378 if ( ! isRpmConfigBackup( str_r ) )
1379 {
1380 Pathname needrebootFile { needrebootDir / str_r };
1381 if ( PathInfo( needrebootFile ).isFile() )
1382 needrebootSpec.parseFrom( needrebootFile );
1383 }
1384 return true;
1385 });
1386 }
1387 satpool.setNeedrebootSpec( std::move(needrebootSpec) );
1388 }
1389
1390 if ( ZConfig::instance().apply_locks_file() )
1391 {
1392 const HardLocksFile::Data & hardLocks( _hardLocksFile.data() );
1393 if ( ! hardLocks.empty() )
1394 {
1395 ResPool::instance().setHardLockQueries( hardLocks );
1396 }
1397 }
1398
1399 // now that the target is loaded, we can cache the flavor
1400 createLastDistributionFlavorCache();
1401
1402 MIL << "Target loaded: " << system.solvablesSize() << " resolvables" << endl;
1403 }
1404
1406 //
1407 // COMMIT
1408 //
1410 ZYppCommitResult TargetImpl::commit( ResPool pool_r, const ZYppCommitPolicy & policy_rX )
1411 {
1412 // ----------------------------------------------------------------- //
1413 ZYppCommitPolicy policy_r( policy_rX );
1414 bool explicitDryRun = policy_r.dryRun(); // explicit dry run will trigger a fileconflict check, implicit (download-only) not.
1415
1416 ShutdownLockCommit lck("zypp");
1417
1418 // Fake outstanding YCP fix: Honour restriction to media 1
1419 // at installation, but install all remaining packages if post-boot.
1420 if ( policy_r.restrictToMedia() > 1 )
1421 policy_r.allMedia();
1422
1423 if ( policy_r.downloadMode() == DownloadDefault ) {
1424 if ( root() == "/" )
1425 policy_r.downloadMode(DownloadInHeaps);
1426 else {
1427 if ( policy_r.singleTransModeEnabled() )
1428 policy_r.downloadMode(DownloadInAdvance);
1429 else
1430 policy_r.downloadMode(DownloadAsNeeded);
1431 }
1432 }
1433 // DownloadOnly implies dry-run.
1434 else if ( policy_r.downloadMode() == DownloadOnly )
1435 policy_r.dryRun( true );
1436 // ----------------------------------------------------------------- //
1437
1438 MIL << "TargetImpl::commit(<pool>, " << policy_r << ")" << endl;
1439
1441 // Compute transaction:
1443 ZYppCommitResult result( root() );
1444 result.rTransaction() = pool_r.resolver().getTransaction();
1445 result.rTransaction().order();
1446 // steps: this is our todo-list
1447 ZYppCommitResult::TransactionStepList & steps( result.rTransactionStepList() );
1448 if ( policy_r.restrictToMedia() )
1449 {
1450 // Collect until the 1st package from an unwanted media occurs.
1451 // Further collection could violate install order.
1452 MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl;
1453 for_( it, result.transaction().begin(), result.transaction().end() )
1454 {
1455 if ( makeResObject( *it )->mediaNr() > 1 )
1456 break;
1457 steps.push_back( *it );
1458 }
1459 }
1460 else
1461 {
1462 result.rTransactionStepList().insert( steps.end(), result.transaction().begin(), result.transaction().end() );
1463 }
1464 MIL << "Todo: " << result << endl;
1465
1467 // Prepare execution of commit plugins:
1469 PluginExecutor commitPlugins;
1470
1471 if ( ( root() == "/" || zypp::env::TRANSACTIONAL_UPDATE() ) && ! policy_r.dryRun() )
1472 {
1473 commitPlugins.load( ZConfig::instance().pluginsPath()/"commit" );
1474 }
1475 if ( commitPlugins )
1476 commitPlugins.send( transactionPluginFrame( "COMMITBEGIN", steps ) );
1477
1479 // Write out a testcase if we're in dist upgrade mode.
1481 if ( pool_r.resolver().upgradeMode() || pool_r.resolver().upgradingRepos() )
1482 {
1483 if ( ! policy_r.dryRun() )
1484 {
1485 writeUpgradeTestcase();
1486 }
1487 else
1488 {
1489 DBG << "dryRun: Not writing upgrade testcase." << endl;
1490 }
1491 }
1492
1494 // Store non-package data:
1496 if ( ! policy_r.dryRun() )
1497 {
1498 filesystem::assert_dir( home() );
1499 // requested locales
1500 _requestedLocalesFile.setLocales( pool_r.getRequestedLocales() );
1501 // autoinstalled
1502 {
1503 SolvIdentFile::Data newdata;
1504 for ( sat::Queue::value_type id : result.rTransaction().autoInstalled() )
1505 newdata.insert( IdString(id) );
1506 _autoInstalledFile.setData( newdata );
1507 }
1508 // hard locks
1509 if ( ZConfig::instance().apply_locks_file() )
1510 {
1511 HardLocksFile::Data newdata;
1512 pool_r.getHardLockQueries( newdata );
1513 _hardLocksFile.setData( newdata );
1514 }
1515 }
1516 else
1517 {
1518 DBG << "dryRun: Not storing non-package data." << endl;
1519 }
1520
1522 // First collect and display all messages
1523 // associated with patches to be installed.
1525 if ( ! policy_r.dryRun() )
1526 {
1527 for_( it, steps.begin(), steps.end() )
1528 {
1529 if ( ! it->satSolvable().isKind<Patch>() )
1530 continue;
1531
1532 PoolItem pi( *it );
1533 if ( ! pi.status().isToBeInstalled() )
1534 continue;
1535
1536 Patch::constPtr patch( asKind<Patch>(pi.resolvable()) );
1537 if ( ! patch ||patch->message().empty() )
1538 continue;
1539
1540 MIL << "Show message for " << patch << endl;
1541 callback::SendReport<target::PatchMessageReport> report;
1542 if ( ! report->show( patch ) )
1543 {
1544 WAR << "commit aborted by the user" << endl;
1545 ZYPP_THROW( TargetAbortedException( ) );
1546 }
1547 }
1548 }
1549 else
1550 {
1551 DBG << "dryRun: Not checking patch messages." << endl;
1552 }
1553
1555 // Remove/install packages.
1557
1558 DBG << "commit log file is set to: " << HistoryLog::fname() << endl;
1559 if ( ! policy_r.dryRun() || policy_r.downloadMode() == DownloadOnly )
1560 {
1561 // Prepare the package cache. Pass all items requiring download.
1562 CommitPackageCache packageCache;
1563 packageCache.setCommitList( steps.begin(), steps.end() );
1564
1565 bool miss = false;
1566 std::unique_ptr<CommitPackagePreloader> preloader;
1567 if ( policy_r.downloadMode() != DownloadAsNeeded )
1568 {
1569 {
1570 // concurrently preload the download cache as a workaround until we have
1571 // migration to full async workflows ready
1572 preloader = std::make_unique<CommitPackagePreloader>();
1573 preloader->preloadTransaction( steps );
1574 miss = preloader->missed ();
1575 }
1576
1577 if ( !miss ) {
1578 // Preload the cache. Until now this means pre-loading all packages.
1579 // Once DownloadInHeaps is fully implemented, this will change and
1580 // we may actually have more than one heap.
1581 for_( it, steps.begin(), steps.end() )
1582 {
1583 switch ( it->stepType() )
1584 {
1585 case sat::Transaction::TRANSACTION_INSTALL:
1586 case sat::Transaction::TRANSACTION_MULTIINSTALL:
1587 // proceed: only install actionas may require download.
1588 break;
1589
1590 default:
1591 // next: no download for or non-packages and delete actions.
1592 continue;
1593 break;
1594 }
1595
1596 PoolItem pi( *it );
1597 if ( pi->isKind<Package>() || pi->isKind<SrcPackage>() )
1598 {
1599 ManagedFile localfile;
1600 try
1601 {
1602 localfile = packageCache.get( pi );
1603 localfile.resetDispose(); // keep the package file in the cache
1604 }
1605 catch ( const AbortRequestException & exp )
1606 {
1607 it->stepStage( sat::Transaction::STEP_ERROR );
1608 miss = true;
1609 WAR << "commit cache preload aborted by the user" << endl;
1610 ZYPP_THROW( TargetAbortedException( ) );
1611 break;
1612 }
1613 catch ( const SkipRequestException & exp )
1614 {
1615 ZYPP_CAUGHT( exp );
1616 it->stepStage( sat::Transaction::STEP_ERROR );
1617 miss = true;
1618 WAR << "Skipping cache preload package " << pi->asKind<Package>() << " in commit" << endl;
1619 continue;
1620 }
1621 catch ( const Exception & exp )
1622 {
1623 // bnc #395704: missing catch causes abort.
1624 // TODO see if packageCache fails to handle errors correctly.
1625 ZYPP_CAUGHT( exp );
1626 it->stepStage( sat::Transaction::STEP_ERROR );
1627 miss = true;
1628 INT << "Unexpected Error: Skipping cache preload package " << pi->asKind<Package>() << " in commit" << endl;
1629 continue;
1630 }
1631 }
1632 }
1633 packageCache.preloaded( true ); // try to avoid duplicate infoInCache CBs in commit
1634 }
1635 }
1636
1637 if ( miss )
1638 {
1639 ERR << "Some packages could not be provided. Aborting commit."<< endl;
1640 }
1641 else
1642 {
1643 if ( ! policy_r.dryRun() )
1644 {
1645
1646 if ( policy_r.singleTransModeEnabled() ) {
1647 commitInSingleTransaction( policy_r, packageCache, result );
1648 } else {
1649 // if cache is preloaded, check for file conflicts
1650 commitFindFileConflicts( policy_r, result );
1651 commit( policy_r, packageCache, result );
1652 }
1653
1654 if ( preloader )
1655 preloader->cleanupCaches ();
1656 }
1657 else
1658 {
1659 DBG << "dryRun/downloadOnly: Not installing/deleting anything." << endl;
1660 if ( explicitDryRun ) {
1661 if ( policy_r.singleTransModeEnabled() ) {
1662 // single trans mode does a test install via rpm
1663 commitInSingleTransaction( policy_r, packageCache, result );
1664 } else {
1665 // if cache is preloaded, check for file conflicts
1666 commitFindFileConflicts( policy_r, result );
1667 }
1668 }
1669 }
1670 }
1671 }
1672 else
1673 {
1674 DBG << "dryRun: Not downloading/installing/deleting anything." << endl;
1675 if ( explicitDryRun ) {
1676 // if cache is preloaded, check for file conflicts
1677 commitFindFileConflicts( policy_r, result );
1678 }
1679 }
1680
1681 {
1682 // NOTE: Removing rpm in a transaction, rpm removes the /var/lib/rpm compat symlink.
1683 // We re-create it, in case it was lost to prevent legacy tools from accidentally
1684 // assuming no database is present.
1685 if ( ! PathInfo(_root/"/var/lib/rpm",PathInfo::LSTAT).isExist()
1686 && PathInfo(_root/"/usr/lib/sysimage/rpm").isDir() ) {
1687 WAR << "(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl;
1688 filesystem::assert_dir( _root/"/var/lib" );
1689 filesystem::symlink( "../../usr/lib/sysimage/rpm", _root/"/var/lib/rpm" );
1690 }
1691 }
1692
1694 // Send result to commit plugins:
1696 if ( commitPlugins )
1697 commitPlugins.send( transactionPluginFrame( "COMMITEND", steps ) );
1698
1700 // Try to rebuild solv file while rpm database is still in cache
1702 if ( ! policy_r.dryRun() )
1703 {
1704 buildCache();
1705 }
1706
1707 MIL << "TargetImpl::commit(<pool>, " << policy_r << ") returns: " << result << endl;
1708 return result;
1709 }
1710
1712 //
1713 // COMMIT internal
1714 //
1716 namespace
1717 {
1718 struct NotifyAttemptToModify
1719 {
1720 NotifyAttemptToModify( ZYppCommitResult & result_r ) : _result( result_r ) {}
1721
1722 void operator()()
1723 { if ( _guard ) { _result.attemptToModify( true ); _guard = false; } }
1724
1725 TrueBool _guard;
1726 ZYppCommitResult & _result;
1727 };
1728 } // namespace
1729
1730 void TargetImpl::commit( const ZYppCommitPolicy & policy_r,
1731 CommitPackageCache & packageCache_r,
1732 ZYppCommitResult & result_r )
1733 {
1734 env::ScopedSet envguard[] __attribute__ ((__unused__)) {
1735 { "ZYPP_SINGLE_RPMTRANS", nullptr },
1736 { "ZYPP_CLASSIC_RPMTRANS", "1" },
1737 };
1738
1739 // steps: this is our todo-list
1740 ZYppCommitResult::TransactionStepList & steps( result_r.rTransactionStepList() );
1741 MIL << "TargetImpl::commit(<list>" << policy_r << ")" << steps.size() << endl;
1742
1743 HistoryLog().stampCommand();
1744
1745 // Send notification once upon 1st call to rpm
1746 NotifyAttemptToModify attemptToModify( result_r );
1747
1748 bool abort = false;
1749
1750 // bsc#1181328: Some systemd tools require /proc to be mounted
1751 AssertProcMounted assertProcMounted( _root );
1752 AssertDevMounted assertDevMounted( _root ); // also /dev
1753
1754 RpmPostTransCollector postTransCollector( _root );
1755 // bsc#1243279: %posttrans needs to know whether the package was installed or updated.
1756 // we collect the names of obsoleted packages. If %posttrans of an obsoleted package
1757 // was collected, it was an upadte.
1758 IdStringSet obsoletedPackages;
1759 std::vector<sat::Solvable> successfullyInstalledPackages;
1760 TargetImpl::PoolItemList remaining;
1761
1762 for_( step, steps.begin(), steps.end() )
1763 {
1764 PoolItem citem( *step );
1765 if ( step->stepType() == sat::Transaction::TRANSACTION_IGNORE )
1766 {
1767 if ( citem->isKind<Package>() )
1768 {
1769 // for packages this means being obsoleted (by rpm)
1770 // thus no additional action is needed.
1771 obsoletedPackages.insert( citem->ident() );
1772 step->stepStage( sat::Transaction::STEP_DONE );
1773 continue;
1774 }
1775 }
1776
1777 if ( citem->isKind<Package>() )
1778 {
1779 Package::constPtr p = citem->asKind<Package>();
1780 if ( citem.status().isToBeInstalled() )
1781 {
1782 ManagedFile localfile;
1783 try
1784 {
1785 localfile = packageCache_r.get( citem );
1786 }
1787 catch ( const AbortRequestException &e )
1788 {
1789 WAR << "commit aborted by the user" << endl;
1790 abort = true;
1791 step->stepStage( sat::Transaction::STEP_ERROR );
1792 break;
1793 }
1794 catch ( const SkipRequestException &e )
1795 {
1796 ZYPP_CAUGHT( e );
1797 WAR << "Skipping package " << p << " in commit" << endl;
1798 step->stepStage( sat::Transaction::STEP_ERROR );
1799 continue;
1800 }
1801 catch ( const Exception &e )
1802 {
1803 // bnc #395704: missing catch causes abort.
1804 // TODO see if packageCache fails to handle errors correctly.
1805 ZYPP_CAUGHT( e );
1806 INT << "Unexpected Error: Skipping package " << p << " in commit" << endl;
1807 step->stepStage( sat::Transaction::STEP_ERROR );
1808 continue;
1809 }
1810
1811 // create a installation progress report proxy
1812 RpmInstallPackageReceiver progress( citem.resolvable() );
1813 progress.connect(); // disconnected on destruction.
1814
1815 bool success = false;
1816 rpm::RpmInstFlags flags( policy_r.rpmInstFlags() & rpm::RPMINST_JUSTDB );
1817 // Why force and nodeps?
1818 //
1819 // Because zypp builds the transaction and the resolver asserts that
1820 // everything is fine.
1821 // We use rpm just to unpack and register the package in the database.
1822 // We do this step by step, so rpm is not aware of the bigger context.
1823 // So we turn off rpms internal checks, because we do it inside zypp.
1824 flags |= rpm::RPMINST_NODEPS;
1825 flags |= rpm::RPMINST_FORCE;
1826 //
1827 if (p->multiversionInstall()) flags |= rpm::RPMINST_NOUPGRADE;
1828 if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST;
1829 if (policy_r.rpmExcludeDocs()) flags |= rpm::RPMINST_EXCLUDEDOCS;
1830 if (policy_r.rpmNoSignature()) flags |= rpm::RPMINST_NOSIGNATURE;
1831
1832 attemptToModify();
1833 try
1834 {
1835 progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS_FORCE );
1836 rpm().installPackage( localfile, flags, &postTransCollector );
1837 HistoryLog().install(citem);
1838
1839 if ( progress.aborted() )
1840 {
1841 WAR << "commit aborted by the user" << endl;
1842 localfile.resetDispose(); // keep the package file in the cache
1843 abort = true;
1844 step->stepStage( sat::Transaction::STEP_ERROR );
1845 break;
1846 }
1847 else
1848 {
1849 if ( citem.isNeedreboot() ) {
1850 auto rebootNeededFile = root() / "/run/reboot-needed";
1851 if ( filesystem::assert_file( rebootNeededFile ) == EEXIST)
1852 filesystem::touch( rebootNeededFile );
1853 }
1854
1855 success = true;
1856 step->stepStage( sat::Transaction::STEP_DONE );
1857 }
1858 }
1859 catch ( Exception & excpt_r )
1860 {
1861 ZYPP_CAUGHT(excpt_r);
1862 localfile.resetDispose(); // keep the package file in the cache
1863
1864 if ( policy_r.dryRun() )
1865 {
1866 WAR << "dry run failed" << endl;
1867 step->stepStage( sat::Transaction::STEP_ERROR );
1868 break;
1869 }
1870 // else
1871 if ( progress.aborted() )
1872 {
1873 WAR << "commit aborted by the user" << endl;
1874 abort = true;
1875 }
1876 else
1877 {
1878 WAR << "Install failed" << endl;
1879 }
1880 step->stepStage( sat::Transaction::STEP_ERROR );
1881 break; // stop
1882 }
1883
1884 if ( success && !policy_r.dryRun() )
1885 {
1886 citem.status().resetTransact( ResStatus::USER );
1887 successfullyInstalledPackages.push_back( citem.satSolvable() );
1888 step->stepStage( sat::Transaction::STEP_DONE );
1889 }
1890 }
1891 else
1892 {
1893 RpmRemovePackageReceiver progress( citem.resolvable() );
1894 progress.connect(); // disconnected on destruction.
1895
1896 bool success = false;
1897 rpm::RpmInstFlags flags( policy_r.rpmInstFlags() & rpm::RPMINST_JUSTDB );
1898 flags |= rpm::RPMINST_NODEPS;
1899 if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST;
1900
1901 attemptToModify();
1902 try
1903 {
1904 rpm().removePackage( p, flags, &postTransCollector );
1905 HistoryLog().remove(citem);
1906
1907 if ( progress.aborted() )
1908 {
1909 WAR << "commit aborted by the user" << endl;
1910 abort = true;
1911 step->stepStage( sat::Transaction::STEP_ERROR );
1912 break;
1913 }
1914 else
1915 {
1916 success = true;
1917 step->stepStage( sat::Transaction::STEP_DONE );
1918 }
1919 }
1920 catch (Exception & excpt_r)
1921 {
1922 ZYPP_CAUGHT( excpt_r );
1923 if ( progress.aborted() )
1924 {
1925 WAR << "commit aborted by the user" << endl;
1926 abort = true;
1927 step->stepStage( sat::Transaction::STEP_ERROR );
1928 break;
1929 }
1930 // else
1931 WAR << "removal of " << p << " failed";
1932 step->stepStage( sat::Transaction::STEP_ERROR );
1933 }
1934 if ( success && !policy_r.dryRun() )
1935 {
1936 citem.status().resetTransact( ResStatus::USER );
1937 step->stepStage( sat::Transaction::STEP_DONE );
1938 }
1939 }
1940 }
1941 else if ( ! policy_r.dryRun() ) // other resolvables (non-Package)
1942 {
1943 // Status is changed as the buddy package buddy
1944 // gets installed/deleted. Handle non-buddies only.
1945 if ( ! citem.buddy() )
1946 {
1947 if ( citem->isKind<Product>() )
1948 {
1949 Product::constPtr p = citem->asKind<Product>();
1950 if ( citem.status().isToBeInstalled() )
1951 {
1952 ERR << "Can't install orphan product without release-package! " << citem << endl;
1953 }
1954 else
1955 {
1956 // Deleting the corresponding product entry is all we con do.
1957 // So the product will no longer be visible as installed.
1958 std::string referenceFilename( p->referenceFilename() );
1959 if ( referenceFilename.empty() )
1960 {
1961 ERR << "Can't remove orphan product without 'referenceFilename'! " << citem << endl;
1962 }
1963 else
1964 {
1965 Pathname referencePath { Pathname("/etc/products.d") / referenceFilename }; // no root prefix for rpmdb lookup!
1966 if ( ! rpm().hasFile( referencePath.asString() ) )
1967 {
1968 // If it's not owned by a package, we can delete it.
1969 referencePath = Pathname::assertprefix( _root, referencePath ); // now add a root prefix
1970 if ( filesystem::unlink( referencePath ) != 0 )
1971 ERR << "Delete orphan product failed: " << referencePath << endl;
1972 }
1973 else
1974 {
1975 WAR << "Won't remove orphan product: '/etc/products.d/" << referenceFilename << "' is owned by a package." << endl;
1976 }
1977 }
1978 }
1979 }
1980 else if ( citem->isKind<SrcPackage>() && citem.status().isToBeInstalled() )
1981 {
1982 // SrcPackage is install-only
1983 SrcPackage::constPtr p = citem->asKind<SrcPackage>();
1984 installSrcPackage( p );
1985 }
1986
1987 citem.status().resetTransact( ResStatus::USER );
1988 step->stepStage( sat::Transaction::STEP_DONE );
1989 }
1990
1991 } // other resolvables
1992
1993 } // for
1994
1995 // Process any remembered %posttrans and/or %transfiletrigger(postun|in)
1996 // scripts. If aborting, at least log if scripts were omitted.
1997 if ( not abort )
1998 postTransCollector.executeScripts( rpm(), obsoletedPackages );
1999 else
2000 postTransCollector.discardScripts();
2001
2002 // Check presence of update scripts/messages. If aborting,
2003 // at least log omitted scripts.
2004 if ( ! successfullyInstalledPackages.empty() )
2005 {
2006 if ( ! RunUpdateScripts( _root, ZConfig::instance().update_scriptsPath(),
2007 successfullyInstalledPackages, abort ) )
2008 {
2009 WAR << "Commit aborted by the user" << endl;
2010 abort = true;
2011 }
2012 // send messages after scripts in case some script generates output,
2013 // that should be kept in t %ghost message file.
2014 RunUpdateMessages( _root, ZConfig::instance().update_messagesPath(),
2015 successfullyInstalledPackages,
2016 result_r );
2017 }
2018
2019 // jsc#SLE-5116: Log patch status changes to history
2020 // NOTE: Should be the last action as it may need to reload
2021 // the Target in case of an incomplete transaction.
2022 logPatchStatusChanges( result_r.transaction(), *this );
2023
2024 if ( abort )
2025 {
2026 HistoryLog().comment( "Commit was aborted." );
2027 ZYPP_THROW( TargetAbortedException( ) );
2028 }
2029 }
2030
2031
2038 struct SendSingleTransReport : public callback::SendReport<rpm::SingleTransReport>
2039 {
2041 void sendLogline( const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg )
2042 {
2043 callback::UserData data { ReportType::contentLogline };
2044 data.set( "line", std::cref(line_r) );
2045 data.set( "level", level_r );
2046 report( data );
2047 }
2048
2049 void sendLoglineRpm( const std::string & line_r, unsigned rpmlevel_r )
2050 {
2051 auto u2rpmlevel = []( unsigned rpmlevel_r ) -> ReportType::loglevel {
2052 switch ( rpmlevel_r ) {
2053 case RPMLOG_EMERG: [[fallthrough]]; // system is unusable
2054 case RPMLOG_ALERT: [[fallthrough]]; // action must be taken immediately
2055 case RPMLOG_CRIT: // critical conditions
2056 return ReportType::loglevel::crt;
2057 case RPMLOG_ERR: // error conditions
2058 return ReportType::loglevel::err;
2059 case RPMLOG_WARNING: // warning conditions
2060 return ReportType::loglevel::war;
2061 default: [[fallthrough]];
2062 case RPMLOG_NOTICE: [[fallthrough]]; // normal but significant condition
2063 case RPMLOG_INFO: // informational
2064 return ReportType::loglevel::msg;
2065 case RPMLOG_DEBUG:
2066 return ReportType::loglevel::dbg;
2067 }
2068 };
2069 sendLogline( line_r, u2rpmlevel( rpmlevel_r ) );
2070 }
2071
2072 private:
2073 void report( const callback::UserData & userData_r )
2074 { (*this)->report( userData_r ); }
2075 };
2076
2077 void TargetImpl::commitInSingleTransaction(const ZYppCommitPolicy &policy_r, CommitPackageCache &packageCache_r, ZYppCommitResult &result_r)
2078 {
2079 env::ScopedSet envguard[] __attribute__ ((__unused__)) {
2080 { "ZYPP_SINGLE_RPMTRANS", "1" },
2081 { "ZYPP_CLASSIC_RPMTRANS", nullptr },
2082 };
2083
2084 SingleTransReportLegacyWrapper _legacyWrapper; // just in case nobody listens on the SendSingleTransReports
2085 SendSingleTransReport report; // active throughout the whole rpm transaction
2086
2087 // steps: this is our todo-list
2088 ZYppCommitResult::TransactionStepList & steps( result_r.rTransactionStepList() );
2089 MIL << "TargetImpl::commit(<list>" << policy_r << ")" << steps.size() << endl;
2090
2091 HistoryLog().stampCommand();
2092
2093 // Send notification once upon calling rpm
2094 NotifyAttemptToModify attemptToModify( result_r );
2095
2096 // let zypper know we executed in one big transaction so in case of failures it can show extended error information
2097 result_r.setSingleTransactionMode( true );
2098
2099 // bsc#1181328: Some systemd tools require /proc to be mounted
2100 AssertProcMounted assertProcMounted( _root );
2101 AssertDevMounted assertDevMounted( _root ); // also /dev
2102
2103 // Why nodeps?
2104 //
2105 // Because zypp builds the transaction and the resolver asserts that
2106 // everything is fine, or the user decided to ignore problems.
2107 rpm::RpmInstFlags flags( policy_r.rpmInstFlags()
2108 | rpm::RPMINST_NODEPS
2109 // skip signature checks, we did that already
2110 | rpm::RPMINST_NODIGEST
2111 | rpm::RPMINST_NOSIGNATURE
2112 // ignore untrusted keys since we already checked those earlier
2113 | rpm::RPMINST_ALLOWUNTRUSTED );
2114
2115 proto::target::Commit commit;
2116 commit.flags = flags;
2117 commit.ignoreArch = ( !ZConfig::instance().systemArchitecture().compatibleWith( ZConfig::instance().defaultSystemArchitecture() ) );
2118 commit.arch = ZConfig::instance().systemArchitecture().asString();
2119 commit.dbPath = rpm().dbPath().asString();
2120 commit.root = rpm().root().asString();
2121 commit.lockFilePath = ZYppFactory::lockfileDir().asString();
2122
2123 bool abort = false;
2124 zypp::AutoDispose<std::unordered_map<int, ManagedFile>> locCache([]( std::unordered_map<int, ManagedFile> &data ){
2125 for ( auto &[_, value] : data ) {
2126 (void)_; // unsused; for older g++ versions
2127 value.resetDispose();
2128 }
2129 data.clear();
2130 });
2131
2132 // fill the transaction
2133 for ( int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) {
2134 auto &step = steps[stepId];
2135 PoolItem citem( step );
2136 if ( step.stepType() == sat::Transaction::TRANSACTION_IGNORE ) {
2137 if ( citem->isKind<Package>() )
2138 {
2139 // for packages this means being obsoleted (by rpm)
2140 // thius no additional action is needed.
2141 step.stepStage( sat::Transaction::STEP_DONE );
2142 continue;
2143 }
2144 }
2145
2146 if ( citem->isKind<Package>() ) {
2147 Package::constPtr p = citem->asKind<Package>();
2148 if ( citem.status().isToBeInstalled() )
2149 {
2150 try {
2151 locCache.value()[stepId] = packageCache_r.get( citem );
2152
2153 proto::target::InstallStep tStep;
2154 tStep.stepId = stepId;
2155 tStep.pathname = locCache.value()[stepId]->asString();
2156 tStep.multiversion = p->multiversionInstall() ;
2157
2158 commit.transactionSteps.push_back( std::move(tStep) );
2159 }
2160 catch ( const AbortRequestException &e )
2161 {
2162 WAR << "commit aborted by the user" << endl;
2163 abort = true;
2164 step.stepStage( sat::Transaction::STEP_ERROR );
2165 break;
2166 }
2167 catch ( const SkipRequestException &e )
2168 {
2169 ZYPP_CAUGHT( e );
2170 WAR << "Skipping package " << p << " in commit" << endl;
2171 step.stepStage( sat::Transaction::STEP_ERROR );
2172 continue;
2173 }
2174 catch ( const Exception &e )
2175 {
2176 // bnc #395704: missing catch causes abort.
2177 // TODO see if packageCache fails to handle errors correctly.
2178 ZYPP_CAUGHT( e );
2179 INT << "Unexpected Error: Skipping package " << p << " in commit" << endl;
2180 step.stepStage( sat::Transaction::STEP_ERROR );
2181 continue;
2182 }
2183 } else {
2184
2185 proto::target::RemoveStep tStep;
2186 tStep.stepId = stepId;
2187 tStep.name = p->name();
2188 tStep.version = p->edition().version();
2189 tStep.release = p->edition().release();
2190 tStep.arch = p->arch().asString();
2191 commit.transactionSteps.push_back(std::move(tStep));
2192
2193 }
2194 } else if ( citem->isKind<SrcPackage>() && citem.status().isToBeInstalled() ) {
2195 // SrcPackage is install-only
2196 SrcPackage::constPtr p = citem->asKind<SrcPackage>();
2197
2198 try {
2199 // provide on local disk
2200 locCache.value()[stepId] = provideSrcPackage( p );
2201
2202 proto::target::InstallStep tStep;
2203 tStep.stepId = stepId;
2204 tStep.pathname = locCache.value()[stepId]->asString();
2205 tStep.multiversion = false;
2206 commit.transactionSteps.push_back(std::move(tStep));
2207
2208 } catch ( const Exception &e ) {
2209 ZYPP_CAUGHT( e );
2210 INT << "Unexpected Error: Skipping package " << p << " in commit" << endl;
2211 step.stepStage( sat::Transaction::STEP_ERROR );
2212 continue;
2213 }
2214 }
2215 }
2216
2217 std::vector<sat::Solvable> successfullyInstalledPackages;
2218
2219 if ( commit.transactionSteps.size() ) {
2220
2221 // create the event loop early
2222 auto loop = zyppng::EventLoop::create();
2223
2224 attemptToModify();
2225
2226 const std::vector<int> interceptedSignals {
2227 SIGINT,
2228 SIGTERM,
2229 SIGHUP,
2230 SIGQUIT
2231 };
2232
2233 auto unixSignals = loop->eventDispatcher()->unixSignalSource();
2234 unixSignals->sigReceived ().connect ([]( int signum ){
2235 // translator: %1% is the received unix signal name, %2% is the numerical value of the received signal
2236 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 });
2238 for( const auto &sig : interceptedSignals )
2239 unixSignals->addSignal ( sig );
2240
2241 Deferred cleanupSigs([&](){
2242 for( const auto &sig : interceptedSignals )
2243 unixSignals->removeSignal ( sig );
2244 });
2245
2246 // transaction related variables:
2247 //
2248 // the index of the step in the transaction list that we currenty execute.
2249 // this can be -1
2250 int currentStepId = -1;
2251
2252 // sync flag, every time zypp-rpm finishes executing a step it writes a tag into
2253 // the script fd, once we receive it we set this flag to true and ignore all output
2254 // that is written to the pipe ( aside from buffering it ) until we finalize the current report
2255 // and start a new one
2256 bool gotEndOfScript = false;
2257
2258 // the possible reports we emit during the transaction
2259 std::unique_ptr<callback::SendReport <rpm::TransactionReportSA>> transactionreport;
2260 std::unique_ptr<callback::SendReport <rpm::InstallResolvableReportSA>> installreport;
2261 std::unique_ptr<callback::SendReport <rpm::RemoveResolvableReportSA>> uninstallreport;
2262 std::unique_ptr<callback::SendReport <rpm::CommitScriptReportSA>> scriptreport;
2263 std::unique_ptr<callback::SendReport <rpm::CleanupPackageReportSA>> cleanupreport;
2264
2265 // this will be set if we receive a transaction error description
2266 std::optional<proto::target::TransactionError> transactionError;
2267
2268 // infos about the currently executed script, empty if no script is currently executed
2269 std::string currentScriptType;
2270 std::string currentScriptPackage;
2271
2272 // buffer to collect rpm output per report, this will be written to the log once the
2273 // report ends
2274 std::string rpmmsg;
2275
2276 // maximum number of lines that we are buffering in rpmmsg
2277 constexpr auto MAXRPMMESSAGELINES = 10000;
2278
2279 // current number of lines in the rpmmsg line buffer. This is capped to MAXRPMMESSAGELINES
2280 unsigned lineno = 0;
2281
2282 // the sources to communicate with zypp-rpm, we will associate pipes with them further down below
2283 auto msgSource = zyppng::AsyncDataSource::create();
2284 auto scriptSource = zyppng::AsyncDataSource::create();
2285
2286 // this will be the communication channel, will be created once the process starts and
2287 // we can receive data
2288 zyppng::StompFrameStreamRef msgStream;
2289
2290
2291 // helper function that sends RPM output to the currently active report, writing a warning to the log
2292 // if there is none
2293 const auto &sendRpmLineToReport = [&]( const std::string &line ){
2294
2295 const auto &sendLogRep = [&]( auto &report, const auto &cType ){
2296 callback::UserData cmdout(cType);
2297 if ( currentStepId >= 0 )
2298 cmdout.set( "solvable", steps.at(currentStepId).satSolvable() );
2299 cmdout.set( "line", line );
2300 report->report(cmdout);
2301 };
2302
2303 if ( installreport ) {
2304 sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout );
2305 } else if ( uninstallreport ) {
2306 sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout );
2307 } else if ( scriptreport ) {
2308 sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout );
2309 } else if ( transactionreport ) {
2310 sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout );
2311 } else if ( cleanupreport ) {
2312 sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout );
2313 } else {
2314 WAR << "Got rpm output without active report " << line; // no endl! - readLine does not trim
2315 }
2316
2317 // remember rpm output
2318 if ( lineno >= MAXRPMMESSAGELINES ) {
2319 if ( line.find( " scriptlet failed, " ) == std::string::npos ) // always log %script errors
2320 return;
2321 }
2322 rpmmsg += line;
2323 if ( line.back() != '\n' )
2324 rpmmsg += '\n';
2325 };
2326
2327
2328 // callback and helper function to process data that is received on the script FD
2329 const auto &processDataFromScriptFd = [&](){
2330
2331 while ( scriptSource->canReadLine() ) {
2332
2333 if ( gotEndOfScript )
2334 return;
2335
2336 std::string l = scriptSource->readLine().asString();
2337 if( str::endsWith( l, endOfScriptTag ) ) {
2338 gotEndOfScript = true;
2339 std::string::size_type rawsize { l.size() - endOfScriptTag.size() };
2340 if ( not rawsize )
2341 return;
2342 l = l.substr( 0, rawsize );
2343 }
2344 L_DBG("zypp-rpm") << "[rpm> " << l; // no endl! - readLine does not trim
2345 sendRpmLineToReport( l );
2346 }
2347 };
2348 scriptSource->sigReadyRead().connect( processDataFromScriptFd );
2349
2350 // helper function that just waits until the end of script tag was received on the scriptSource
2351 const auto &waitForScriptEnd = [&]() {
2352
2353 // nothing to wait for
2354 if ( gotEndOfScript )
2355 return;
2356
2357 // we process all available data
2358 processDataFromScriptFd();
2359
2360 // end of script is always sent by zypp-rpm, we need to wait for it to keep order
2361 while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) {
2362 // readyRead will trigger processDataFromScriptFd so no need to call it again
2363 // we still got nothing, lets wait for more
2364 scriptSource->waitForReadyRead( 100 );
2365 }
2366 };
2367
2368 const auto &aboutToStartNewReport = [&](){
2369
2370 if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) {
2371 ERR << "There is still a running report, this is a bug" << std::endl;
2372 assert(false);
2373 }
2374
2375 gotEndOfScript = false;
2376 };
2377
2378 const auto &writeRpmMsgToHistory = [&](){
2379 if ( rpmmsg.size() == 0 )
2380 return;
2381
2382 if ( lineno >= MAXRPMMESSAGELINES )
2383 rpmmsg += "[truncated]\n";
2384
2385 std::ostringstream sstr;
2386 sstr << "rpm output:" << endl << rpmmsg << endl;
2387 HistoryLog().comment(sstr.str());
2388 };
2389
2390 // helper function that closes the current report and cleans up the ressources
2391 const auto &finalizeCurrentReport = [&]() {
2392 sat::Transaction::Step *step = nullptr;
2393 Resolvable::constPtr resObj;
2394 if ( currentStepId >= 0 ) {
2395 step = &steps.at(currentStepId);
2396 resObj = makeResObject( step->satSolvable() );
2397 }
2398
2399 if ( installreport ) {
2400 waitForScriptEnd();
2401 if ( step->stepStage() == sat::Transaction::STEP_ERROR ) {
2402
2403 HistoryLog().comment(
2404 str::form("%s install failed", step->ident().c_str()),
2405 true /*timestamp*/);
2406
2407 writeRpmMsgToHistory();
2408
2409 ( *installreport)->finish( resObj, rpm::InstallResolvableReportSA::INVALID );
2410 } else {
2411 ( *installreport)->progress( 100, resObj );
2412 ( *installreport)->finish( resObj, rpm::InstallResolvableReportSA::NO_ERROR );
2413
2414 if ( currentStepId >= 0 )
2415 locCache.value().erase( currentStepId );
2416 successfullyInstalledPackages.push_back( step->satSolvable() );
2417
2418 PoolItem citem( *step );
2419 if ( !( flags & rpm::RPMINST_TEST ) ) {
2420 // @TODO are we really doing this just for install?
2421 if ( citem.isNeedreboot() ) {
2422 auto rebootNeededFile = root() / "/run/reboot-needed";
2423 if ( filesystem::assert_file( rebootNeededFile ) == EEXIST)
2424 filesystem::touch( rebootNeededFile );
2425 }
2426 citem.status().resetTransact( ResStatus::USER );
2427 HistoryLog().install(citem);
2428 }
2429
2430 HistoryLog().comment(
2431 str::form("%s installed ok", step->ident().c_str()),
2432 true /*timestamp*/);
2433
2434 writeRpmMsgToHistory();
2435 }
2436 }
2437 if ( uninstallreport ) {
2438 waitForScriptEnd();
2439 if ( step->stepStage() == sat::Transaction::STEP_ERROR ) {
2440
2441 HistoryLog().comment(
2442 str::form("%s uninstall failed", step->ident().c_str()),
2443 true /*timestamp*/);
2444
2445 writeRpmMsgToHistory();
2446
2447 ( *uninstallreport)->finish( resObj, rpm::RemoveResolvableReportSA::INVALID );
2448 } else {
2449 ( *uninstallreport)->progress( 100, resObj );
2450 ( *uninstallreport)->finish( resObj, rpm::RemoveResolvableReportSA::NO_ERROR );
2451
2452 PoolItem citem( *step );
2453 HistoryLog().remove(citem);
2454
2455 HistoryLog().comment(
2456 str::form("%s removed ok", step->ident().c_str()),
2457 true /*timestamp*/);
2458
2459 writeRpmMsgToHistory();
2460 }
2461 }
2462 if ( scriptreport ) {
2463 waitForScriptEnd();
2464 ( *scriptreport)->progress( 100, resObj );
2465 ( *scriptreport)->finish( resObj, rpm::CommitScriptReportSA::NO_ERROR );
2466 }
2467 if ( transactionreport ) {
2468 waitForScriptEnd();
2469 ( *transactionreport)->progress( 100 );
2470 ( *transactionreport)->finish( rpm::TransactionReportSA::NO_ERROR );
2471 }
2472 if ( cleanupreport ) {
2473 waitForScriptEnd();
2474 ( *cleanupreport)->progress( 100 );
2475 ( *cleanupreport)->finish( rpm::CleanupPackageReportSA::NO_ERROR );
2476 }
2477 currentStepId = -1;
2478 lineno = 0;
2479 rpmmsg.clear();
2480 currentScriptType.clear();
2481 currentScriptPackage.clear();
2482 installreport.reset();
2483 uninstallreport.reset();
2484 scriptreport.reset();
2485 transactionreport.reset();
2486 cleanupreport.reset();
2487 };
2488
2489 // This sets up the process and pushes the required transactions steps to it
2490 // careful when changing code here, zypp-rpm relies on the exact order data is transferred:
2491 //
2492 // 1) Size of the commit message , sizeof(zyppng::rpc::HeaderSizeType)
2493 // 2) The Commit Proto message, directly serialized to the FD, without Envelope
2494 // 3) 2 writeable FDs that are set up by the parent Process when forking. The first FD is to be used for message sending, the second one for script output
2495
2496 constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY);
2497
2498 const char *argv[] = {
2499 //"gdbserver",
2500 //"localhost:10001",
2501 zyppRpmBinary.data(),
2502 nullptr
2503 };
2504 auto prog = zyppng::Process::create();
2505
2506 // we set up a pipe to communicate with the process, it is too dangerous to use stdout since librpm
2507 // might print to it.
2508 auto messagePipe = zyppng::Pipe::create();
2509 if ( !messagePipe )
2510 ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to create message pipe" ) );
2511
2512 // open a pipe that we are going to use to receive script output, this is a librpm feature, there is no other
2513 // way than a FD to redirect that output
2514 auto scriptPipe = zyppng::Pipe::create();
2515 if ( !scriptPipe )
2516 ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to create scriptfd" ) );
2517
2518 prog->addFd( messagePipe->writeFd );
2519 prog->addFd( scriptPipe->writeFd );
2520
2521 // set up the AsyncDataSource to read script output
2522 if ( !scriptSource->openFds( std::vector<int>{ scriptPipe->readFd } ) )
2523 ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to open scriptFD to subprocess" ) );
2524
2525 const auto &processMessages = [&] ( ) {
2526
2527 // lambda function that parses the passed message type and checks if the stepId is a valid offset
2528 // in the steps list.
2529 const auto &checkMsgWithStepId = [&steps]( auto &p ){
2530 if ( !p ) {
2531 ERR << "Failed to parse message from zypp-rpm." << std::endl;
2532 return false;
2533 }
2534
2535 auto id = p->stepId;
2536 if ( id < 0 || id >= steps.size() ) {
2537 ERR << "Received invalid stepId: " << id << " in " << p->typeName << " message from zypp-rpm, ignoring." << std::endl;
2538 return false;
2539 }
2540 return true;
2541 };
2542
2543 while ( const auto &m = msgStream->nextMessage() ) {
2544
2545 // due to librpm behaviour we need to make sense of the order of messages we receive
2546 // because we first get a PackageFinished BEFORE getting a PackageError, same applies to
2547 // Script related messages. What we do is remember the current step we are in and only close
2548 // the step when we get the start of the next one
2549 const auto &mName = m->command();
2550 if ( mName == proto::target::RpmLog::typeName ) {
2551
2552 const auto &p = proto::target::RpmLog::fromStompMessage (*m);
2553 if ( !p ) {
2554 ERR << "Failed to parse " << proto::target::RpmLog::typeName << " message from zypp-rpm." << std::endl;
2555 continue;
2556 }
2557 ( p->level >= RPMLOG_ERR ? L_ERR("zypp-rpm")
2558 : p->level >= RPMLOG_WARNING ? L_WAR("zypp-rpm")
2559 : L_DBG("zypp-rpm") ) << "[rpm " << p->level << "> " << p->line; // no endl! - readLine does not trim
2560 report.sendLoglineRpm( p->line, p->level );
2561
2562 } else if ( mName == proto::target::PackageBegin::typeName ) {
2563 finalizeCurrentReport();
2564
2565 const auto &p = proto::target::PackageBegin::fromStompMessage(*m);
2566 if ( !checkMsgWithStepId( p ) )
2567 continue;
2568
2569 aboutToStartNewReport();
2570
2571 auto & step = steps.at( p->stepId );
2572 currentStepId = p->stepId;
2573 if ( step.stepType() == sat::Transaction::TRANSACTION_ERASE ) {
2574 uninstallreport = std::make_unique< callback::SendReport <rpm::RemoveResolvableReportSA> > ();
2575 ( *uninstallreport )->start( makeResObject( step.satSolvable() ) );
2576 } else {
2577 installreport = std::make_unique< callback::SendReport <rpm::InstallResolvableReportSA> > ();
2578 ( *installreport )->start( makeResObject( step.satSolvable() ) );
2579 }
2580
2581 } else if ( mName == proto::target::PackageFinished::typeName ) {
2582 const auto &p = proto::target::PackageFinished::fromStompMessage(*m);
2583 if ( !checkMsgWithStepId( p ) )
2584 continue;
2585
2586 // here we only set the step stage to done, we however need to wait for the next start in order to send
2587 // the finished report since there might be a error pending to be reported
2588 steps[ p->stepId ].stepStage( sat::Transaction::STEP_DONE );
2589
2590 } else if ( mName == proto::target::PackageProgress::typeName ) {
2591 const auto &p = proto::target::PackageProgress::fromStompMessage(*m);
2592 if ( !checkMsgWithStepId( p ) )
2593 continue;
2594
2595 if ( uninstallreport )
2596 (*uninstallreport)->progress( p->amount, makeResObject( steps.at( p->stepId ) ));
2597 else if ( installreport )
2598 (*installreport)->progress( p->amount, makeResObject( steps.at( p->stepId ) ));
2599 else
2600 ERR << "Received a " << mName << " message but there is no corresponding report running." << std::endl;
2601
2602 } else if ( mName == proto::target::PackageError::typeName ) {
2603 const auto &p = proto::target::PackageError::fromStompMessage(*m);
2604 if ( !checkMsgWithStepId( p ) )
2605 continue;
2606
2607 if ( p->stepId >= 0 && p->stepId < steps.size() )
2608 steps[ p->stepId ].stepStage( sat::Transaction::STEP_ERROR );
2609
2610 finalizeCurrentReport();
2611
2612 } else if ( mName == proto::target::ScriptBegin::typeName ) {
2613 finalizeCurrentReport();
2614
2615 const auto &p = proto::target::ScriptBegin::fromStompMessage(*m);
2616 if ( !p ) {
2617 ERR << "Failed to parse " << proto::target::ScriptBegin::typeName << " message from zypp-rpm." << std::endl;
2618 continue;
2619 }
2620
2621 aboutToStartNewReport();
2622
2623 Resolvable::constPtr resPtr;
2624 const auto stepId = p->stepId;
2625 if ( stepId >= 0 && static_cast<size_t>(stepId) < steps.size() ) {
2626 resPtr = makeResObject( steps.at(stepId).satSolvable() );
2627 }
2628
2629 currentStepId = p->stepId;
2630 scriptreport = std::make_unique< callback::SendReport <rpm::CommitScriptReportSA> > ();
2631 currentScriptType = p->scriptType;
2632 currentScriptPackage = p->scriptPackage;
2633 (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr );
2634
2635 } else if ( mName == proto::target::ScriptFinished::typeName ) {
2636
2637 // we just read the message, we do not act on it because a ScriptError is reported after ScriptFinished
2638
2639 } else if ( mName == proto::target::ScriptError::typeName ) {
2640
2641 const auto &p = proto::target::ScriptError::fromStompMessage(*m);
2642 if ( !p ) {
2643 ERR << "Failed to parse " << proto::target::ScriptError::typeName << " message from zypp-rpm." << std::endl;
2644 continue;
2645 }
2646
2647 Resolvable::constPtr resPtr;
2648 const auto stepId = p->stepId;
2649 if ( stepId >= 0 && static_cast<size_t>(stepId) < steps.size() ) {
2650 resPtr = makeResObject( steps.at(stepId).satSolvable() );
2651
2652 if ( p->fatal ) {
2653 steps.at( stepId ).stepStage( sat::Transaction::STEP_ERROR );
2654 }
2655
2656 }
2657
2658 HistoryLog().comment(
2659 str::form("Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() : "unknown" ),
2660 true /*timestamp*/);
2661
2662 writeRpmMsgToHistory();
2663
2664 if ( !scriptreport ) {
2665 ERR << "Received a ScriptError message, but there is no running report. " << std::endl;
2666 continue;
2667 }
2668
2669 // before killing the report we need to wait for the script end tag
2670 waitForScriptEnd();
2671 (*scriptreport)->finish( resPtr, p->fatal ? rpm::CommitScriptReportSA::CRITICAL : rpm::CommitScriptReportSA::WARN );
2672
2673 // manually reset the current report since we already sent the finish(), rest will be reset by the new start
2674 scriptreport.reset();
2675 currentStepId = -1;
2676
2677 } else if ( mName == proto::target::CleanupBegin::typeName ) {
2678 finalizeCurrentReport();
2679
2680 const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m);
2681 if ( !beg ) {
2682 ERR << "Failed to parse " << proto::target::CleanupBegin::typeName << " message from zypp-rpm." << std::endl;
2683 continue;
2684 }
2685
2686 aboutToStartNewReport();
2687 cleanupreport = std::make_unique< callback::SendReport <rpm::CleanupPackageReportSA> > ();
2688 (*cleanupreport)->start( beg->nvra );
2689 } else if ( mName == proto::target::CleanupFinished::typeName ) {
2690
2691 finalizeCurrentReport();
2692
2693 } else if ( mName == proto::target::CleanupProgress::typeName ) {
2694 const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m);
2695 if ( !prog ) {
2696 ERR << "Failed to parse " << proto::target::CleanupProgress::typeName << " message from zypp-rpm." << std::endl;
2697 continue;
2698 }
2699
2700 if ( !cleanupreport ) {
2701 ERR << "Received a CleanupProgress message, but there is no running report. " << std::endl;
2702 continue;
2703 }
2704
2705 (*cleanupreport)->progress( prog->amount );
2706
2707 } else if ( mName == proto::target::TransBegin::typeName ) {
2708 finalizeCurrentReport();
2709
2710 const auto &beg = proto::target::TransBegin::fromStompMessage(*m);
2711 if ( !beg ) {
2712 ERR << "Failed to parse " << proto::target::TransBegin::typeName << " message from zypp-rpm." << std::endl;
2713 continue;
2714 }
2715
2716 aboutToStartNewReport();
2717 transactionreport = std::make_unique< callback::SendReport <rpm::TransactionReportSA> > ();
2718 (*transactionreport)->start( beg->name );
2719 } else if ( mName == proto::target::TransFinished::typeName ) {
2720
2721 finalizeCurrentReport();
2722
2723 } else if ( mName == proto::target::TransProgress::typeName ) {
2724 const auto &prog = proto::target::TransProgress::fromStompMessage(*m);
2725 if ( !prog ) {
2726 ERR << "Failed to parse " << proto::target::TransProgress::typeName << " message from zypp-rpm." << std::endl;
2727 continue;
2728 }
2729
2730 if ( !transactionreport ) {
2731 ERR << "Received a TransactionProgress message, but there is no running report. " << std::endl;
2732 continue;
2733 }
2734
2735 (*transactionreport)->progress( prog->amount );
2736 } else if ( mName == proto::target::TransactionError::typeName ) {
2737
2738 const auto &error = proto::target::TransactionError::fromStompMessage(*m);
2739 if ( !error ) {
2740 ERR << "Failed to parse " << proto::target::TransactionError::typeName << " message from zypp-rpm." << std::endl;
2741 continue;
2742 }
2743
2744 // this value is checked later
2745 transactionError = std::move(*error);
2746
2747 } else {
2748 ERR << "Received unexpected message from zypp-rpm: "<< m->command() << ", ignoring" << std::endl;
2749 return;
2750 }
2751
2752 }
2753 };
2754
2755 // setup the rest when zypp-rpm is running
2756 prog->sigStarted().connect( [&](){
2757
2758 // close the ends of the pipes we do not care about
2759 messagePipe->unrefWrite();
2760 scriptPipe->unrefWrite();
2761
2762 // read the stdout and stderr and forward it to our log
2763 prog->connectFunc( &zyppng::IODevice::sigChannelReadyRead, [&]( int channel ){
2764 while( prog->canReadLine( channel ) ) {
2765 L_ERR("zypp-rpm") << ( channel == zyppng::Process::StdOut ? "<stdout> " : "<stderr> " ) << prog->channelReadLine( channel ).asStringView(); // no endl! - readLine does not trim
2766 }
2767 });
2768
2769 // this is the source for control messages from zypp-rpm , we will get structured data information
2770 // in form of STOMP messages
2771 if ( !msgSource->openFds( std::vector<int>{ messagePipe->readFd }, prog->stdinFd() ) )
2772 ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to open read stream to subprocess" ) );
2773
2774 msgStream = zyppng::StompFrameStream::create(msgSource);
2775 msgStream->connectFunc( &zyppng::StompFrameStream::sigMessageReceived, processMessages );
2776
2777 const auto &msg = commit.toStompMessage();
2778 if ( !msg )
2779 std::rethrow_exception ( msg.error() );
2780
2781 if ( !msgStream->sendMessage( *msg ) ) {
2782 prog->stop( SIGKILL );
2783 ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to write commit to subprocess" ) );
2784 }
2785 });
2786
2787 // track the childs lifetime
2788 int zyppRpmExitCode = -1;
2789 prog->connectFunc( &zyppng::Process::sigFinished, [&]( int code ){
2790 zyppRpmExitCode = code;
2791 loop->quit();
2792 });
2793
2794 if ( !prog->start( argv ) ) {
2795 HistoryLog().comment( "Commit was aborted, failed to run zypp-rpm" );
2796 ZYPP_THROW( target::rpm::RpmSubprocessException( prog->execError() ) );
2797 }
2798
2799 loop->run();
2800
2801 if ( msgStream ) {
2802 // pull all messages from the IO device
2803 msgStream->readAllMessages();
2804
2805 // make sure to read ALL available messages
2806 processMessages();
2807 }
2808
2809 // we will not receive a new start message , so we need to manually finalize the last report
2810 finalizeCurrentReport();
2811
2812 // make sure to read all data from the log source
2813 bool readMsgs = false;
2814 while( prog->canReadLine( zyppng::Process::StdErr ) ) {
2815 readMsgs = true;
2816 MIL << "zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdErr ).asStringView();
2817 }
2818 while( prog->canReadLine( zyppng::Process::StdOut ) ) {
2819 readMsgs = true;
2820 MIL << "zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdOut ).asStringView();
2821 }
2822
2823 while ( scriptSource->canReadLine() ) {
2824 readMsgs = true;
2825 MIL << "rpm-script-fd: " << scriptSource->readLine().asStringView();
2826 }
2827 if ( scriptSource->bytesAvailable() > 0 ) {
2828 readMsgs = true;
2829 MIL << "rpm-script-fd: " << scriptSource->readAll().asStringView();
2830 }
2831 if ( readMsgs )
2832 MIL << std::endl;
2833
2834 switch ( zyppRpmExitCode ) {
2835 // we need to look at the summary, handle finishedwitherrors like no error here
2836 case zypprpm::NoError:
2837 case zypprpm::RpmFinishedWithError:
2838 break;
2839 case zypprpm::RpmFinishedWithTransactionError: {
2840 // here zypp-rpm sent us a error description
2841 if ( transactionError ) {
2842
2843 std::ostringstream sstr;
2844 sstr << _("Executing the transaction failed because of the following problems:") << "\n";
2845 for ( const auto & err : transactionError->problems ) {
2846 sstr << " " << err << "\n";
2847 }
2848 sstr << std::endl;
2849 ZYPP_THROW( rpm::RpmTransactionFailedException( sstr.str() ) );
2850
2851 } else {
2852 ZYPP_THROW( rpm::RpmTransactionFailedException("RPM failed with a unexpected error, check the logs for more information.") );
2853 }
2854 break;
2855 }
2856 case zypprpm::FailedToOpenDb:
2857 ZYPP_THROW( rpm::RpmDbOpenException( rpm().root(), rpm().dbPath() ) );
2858 break;
2859 case zypprpm::WrongHeaderSize:
2860 case zypprpm::WrongMessageFormat:
2861 ZYPP_THROW( rpm::RpmSubprocessException("Failed to communicate with zypp-rpm, this is most likely a bug. Consider to fall back to legacy transaction strategy.") );
2862 break;
2863 case zypprpm::RpmInitFailed:
2864 ZYPP_THROW( rpm::RpmInitException( rpm().root(), rpm().dbPath() ) );
2865 break;
2866 case zypprpm::FailedToReadPackage:
2867 ZYPP_THROW( rpm::RpmSubprocessException("zypp-rpm was unable to read a package, check the logs for more information.") );
2868 break;
2869 case zypprpm::FailedToAddStepToTransaction:
2870 ZYPP_THROW( rpm::RpmSubprocessException("zypp-rpm failed to build the transaction, check the logs for more information.") );
2871 break;
2872 case zypprpm::RpmOrderFailed:
2873 ZYPP_THROW( rpm::RpmSubprocessException("zypp-rpm failed to order the transaction, check the logs for more information.") );
2874 break;
2875 case zypprpm::FailedToCreateLock:
2876 ZYPP_THROW( rpm::RpmSubprocessException("zypp-rpm failed to create its lockfile, check the logs for more information.") );
2877 break;
2878 }
2879
2880 for ( int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) {
2881 auto &step = steps[stepId];
2882 PoolItem citem( step );
2883
2884 if ( step.stepStage() == sat::Transaction::STEP_TODO ) {
2885 // other resolvables (non-Package) that are not handled by zypp-rpm
2886 if ( !citem->isKind<Package>() && !policy_r.dryRun() ) {
2887 // Status is changed as the buddy package buddy
2888 // gets installed/deleted. Handle non-buddies only.
2889 if ( ! citem.buddy() && citem->isKind<Product>() ) {
2890 Product::constPtr p = citem->asKind<Product>();
2891
2892 if ( citem.status().isToBeInstalled() ) {
2893 ERR << "Can't install orphan product without release-package! " << citem << endl;
2894 } else {
2895 // Deleting the corresponding product entry is all we con do.
2896 // So the product will no longer be visible as installed.
2897 std::string referenceFilename( p->referenceFilename() );
2898
2899 if ( referenceFilename.empty() ) {
2900 ERR << "Can't remove orphan product without 'referenceFilename'! " << citem << endl;
2901 } else {
2902 Pathname referencePath { Pathname("/etc/products.d") / referenceFilename }; // no root prefix for rpmdb lookup!
2903
2904 if ( ! rpm().hasFile( referencePath.asString() ) ) {
2905 // If it's not owned by a package, we can delete it.
2906 referencePath = Pathname::assertprefix( _root, referencePath ); // now add a root prefix
2907 if ( filesystem::unlink( referencePath ) != 0 )
2908 ERR << "Delete orphan product failed: " << referencePath << endl;
2909 } else {
2910 WAR << "Won't remove orphan product: '/etc/products.d/" << referenceFilename << "' is owned by a package." << endl;
2911 }
2912 }
2913 }
2914 citem.status().resetTransact( ResStatus::USER );
2915 step.stepStage( sat::Transaction::STEP_DONE );
2916 }
2917 }
2918 }
2919 }
2920 }
2921
2922 // Check presence of update scripts/messages. If aborting,
2923 // at least log omitted scripts.
2924 if ( ! successfullyInstalledPackages.empty() )
2925 {
2926 if ( ! RunUpdateScripts( _root, ZConfig::instance().update_scriptsPath(),
2927 successfullyInstalledPackages, abort ) )
2928 {
2929 WAR << "Commit aborted by the user" << endl;
2930 abort = true;
2931 }
2932 // send messages after scripts in case some script generates output,
2933 // that should be kept in t %ghost message file.
2934 RunUpdateMessages( _root, ZConfig::instance().update_messagesPath(),
2935 successfullyInstalledPackages,
2936 result_r );
2937 }
2938
2939 // jsc#SLE-5116: Log patch status changes to history
2940 // NOTE: Should be the last action as it may need to reload
2941 // the Target in case of an incomplete transaction.
2942 logPatchStatusChanges( result_r.transaction(), *this );
2943
2944 if ( abort ) {
2945 HistoryLog().comment( "Commit was aborted." );
2946 ZYPP_THROW( TargetAbortedException( ) );
2947 }
2948 }
2949
2951
2952 rpm::RpmDb & TargetImpl::rpm()
2953 {
2954 return _rpm;
2955 }
2956
2957 bool TargetImpl::providesFile (const std::string & path_str, const std::string & name_str) const
2958 {
2959 return _rpm.hasFile(path_str, name_str);
2960 }
2961
2963 namespace
2964 {
2965 parser::ProductFileData baseproductdata( const Pathname & root_r )
2966 {
2967 parser::ProductFileData ret;
2968 PathInfo baseproduct( Pathname::assertprefix( root_r, "/etc/products.d/baseproduct" ) );
2969
2970 if ( baseproduct.isFile() )
2971 {
2972 try
2973 {
2974 ret = parser::ProductFileReader::scanFile( baseproduct.path() );
2975 }
2976 catch ( const Exception & excpt )
2977 {
2978 ZYPP_CAUGHT( excpt );
2979 }
2980 }
2981 else if ( PathInfo( Pathname::assertprefix( root_r, "/etc/products.d" ) ).isDir() )
2982 {
2983 ERR << "baseproduct symlink is dangling or missing: " << baseproduct << endl;
2984 }
2985 return ret;
2986 }
2987
2988 inline Pathname staticGuessRoot( const Pathname & root_r )
2989 {
2990 if ( root_r.empty() )
2991 {
2992 // empty root: use existing Target or assume "/"
2993 Pathname ret ( ZConfig::instance().systemRoot() );
2994 if ( ret.empty() )
2995 return Pathname("/");
2996 return ret;
2997 }
2998 return root_r;
2999 }
3000
3001 inline std::string firstNonEmptyLineIn( const Pathname & file_r )
3002 {
3003 std::ifstream idfile( file_r.c_str() );
3004 for( iostr::EachLine in( idfile ); in; in.next() )
3005 {
3006 std::string line( str::trim( *in ) );
3007 if ( ! line.empty() )
3008 return line;
3009 }
3010 return std::string();
3011 }
3012 } // namespace
3014
3015 Product::constPtr TargetImpl::baseProduct() const
3016 {
3017 ResPool pool(ResPool::instance());
3018 for_( it, pool.byKindBegin<Product>(), pool.byKindEnd<Product>() )
3019 {
3020 Product::constPtr p = (*it)->asKind<Product>();
3021 if ( p->isTargetDistribution() )
3022 return p;
3023 }
3024 return nullptr;
3025 }
3026
3027 LocaleSet TargetImpl::requestedLocales( const Pathname & root_r )
3028 {
3029 const Pathname needroot( staticGuessRoot(root_r) );
3030 const Target_constPtr target( getZYpp()->getTarget() );
3031 if ( target && target->root() == needroot )
3032 return target->requestedLocales();
3033 return RequestedLocalesFile( home(needroot) / "RequestedLocales" ).locales();
3034 }
3035
3036 void TargetImpl::updateAutoInstalled()
3037 {
3038 MIL << "updateAutoInstalled if changed..." << endl;
3039 SolvIdentFile::Data newdata;
3040 for ( auto id : sat::Pool::instance().autoInstalled() )
3041 newdata.insert( IdString(id) ); // explicit ctor!
3042 _autoInstalledFile.setData( std::move(newdata) );
3043 }
3044
3045 std::string TargetImpl::targetDistribution() const
3046 { return baseproductdata( _root ).registerTarget(); }
3047 // static version:
3048 std::string TargetImpl::targetDistribution( const Pathname & root_r )
3049 { return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); }
3050
3051 std::string TargetImpl::targetDistributionRelease() const
3052 { return baseproductdata( _root ).registerRelease(); }
3053 // static version:
3054 std::string TargetImpl::targetDistributionRelease( const Pathname & root_r )
3055 { return baseproductdata( staticGuessRoot(root_r) ).registerRelease();}
3056
3057 std::string TargetImpl::targetDistributionFlavor() const
3058 { return baseproductdata( _root ).registerFlavor(); }
3059 // static version:
3060 std::string TargetImpl::targetDistributionFlavor( const Pathname & root_r )
3061 { return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();}
3062
3063 Target::DistributionLabel TargetImpl::distributionLabel() const
3064 {
3065 Target::DistributionLabel ret;
3066 parser::ProductFileData pdata( baseproductdata( _root ) );
3067 ret.shortName = pdata.shortName();
3068 ret.summary = pdata.summary();
3069 return ret;
3070 }
3071 // static version:
3072 Target::DistributionLabel TargetImpl::distributionLabel( const Pathname & root_r )
3073 {
3074 Target::DistributionLabel ret;
3075 parser::ProductFileData pdata( baseproductdata( staticGuessRoot(root_r) ) );
3076 ret.shortName = pdata.shortName();
3077 ret.summary = pdata.summary();
3078 return ret;
3079 }
3080
3081 std::string TargetImpl::distributionVersion() const
3082 {
3083 if ( _distributionVersion.empty() )
3084 {
3085 _distributionVersion = TargetImpl::distributionVersion(root());
3086 if ( !_distributionVersion.empty() )
3087 MIL << "Remember distributionVersion = '" << _distributionVersion << "'" << endl;
3088 }
3089 return _distributionVersion;
3090 }
3091 // static version
3092 std::string TargetImpl::distributionVersion( const Pathname & root_r )
3093 {
3094 const Pathname & needroot = staticGuessRoot(root_r);
3095 std::string distributionVersion = baseproductdata( needroot ).edition().version();
3096 if ( distributionVersion.empty() )
3097 {
3098 // ...But the baseproduct method is not expected to work on RedHat derivatives.
3099 // On RHEL, Fedora and others the "product version" is determined by the first package
3100 // providing 'system-release'. This value is not hardcoded in YUM and can be configured
3101 // with the $distroverpkg variable.
3102 rpm::librpmDb::db_const_iterator it( needroot );
3103 if ( it.findByProvides( ZConfig::instance().distroverpkg() ) )
3104 distributionVersion = it->tag_version();
3105 }
3106 return distributionVersion;
3107 }
3108
3109
3110 std::string TargetImpl::distributionFlavor() const
3111 {
3112 return firstNonEmptyLineIn( home() / "LastDistributionFlavor" );
3113 }
3114 // static version:
3115 std::string TargetImpl::distributionFlavor( const Pathname & root_r )
3116 {
3117 return firstNonEmptyLineIn( staticGuessRoot(root_r) / "/var/lib/zypp/LastDistributionFlavor" );
3118 }
3119
3121 namespace
3122 {
3123 std::string guessAnonymousUniqueId( const Pathname & root_r )
3124 {
3125 // bsc#1024741: Omit creating a new uid for chrooted systems (if it already has one, fine)
3126 std::string ret( firstNonEmptyLineIn( root_r / "/var/lib/zypp/AnonymousUniqueId" ) );
3127 if ( ret.empty() && root_r != "/" )
3128 {
3129 // if it has nonoe, use the outer systems one
3130 ret = firstNonEmptyLineIn( "/var/lib/zypp/AnonymousUniqueId" );
3131 }
3132 return ret;
3133 }
3134 }
3135
3136 std::string TargetImpl::anonymousUniqueId() const
3137 {
3138 return guessAnonymousUniqueId( root() );
3139 }
3140 // static version:
3141 std::string TargetImpl::anonymousUniqueId( const Pathname & root_r )
3142 {
3143 return guessAnonymousUniqueId( staticGuessRoot(root_r) );
3144 }
3145
3147
3148 void TargetImpl::vendorAttr( VendorAttr vendorAttr_r )
3149 {
3150 MIL << "New VendorAttr: " << vendorAttr_r << endl;
3151 _vendorAttr = std::move(vendorAttr_r);
3152 }
3153
3154
3155 void TargetImpl::installSrcPackage( const SrcPackage_constPtr & srcPackage_r )
3156 {
3157 // provide on local disk
3158 ManagedFile localfile = provideSrcPackage(srcPackage_r);
3159 // create a installation progress report proxy
3160 RpmInstallPackageReceiver progress( srcPackage_r );
3161 progress.connect(); // disconnected on destruction.
3162 // install it
3163 rpm().installPackage ( localfile );
3164 }
3165
3166 ManagedFile TargetImpl::provideSrcPackage( const SrcPackage_constPtr & srcPackage_r )
3167 {
3168 // provide on local disk
3169 repo::RepoMediaAccess access_r;
3170 repo::SrcPackageProvider prov( access_r );
3171 return prov.provideSrcPackage( srcPackage_r );
3172 }
3173
3174 } // namespace target
3177} // namespace zypp
CommitPackageCache.h
NON_COPYABLE
#define NON_COPYABLE(CLASS)
Delete copy ctor and copy assign.
Definition Easy.h:49
for_
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
NON_MOVABLE
#define NON_MOVABLE(CLASS)
Delete move ctor and move assign.
Definition Easy.h:59
Env.h
Exception.h
ZYPP_CAUGHT
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:475
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
ExternalProgram.h
Functional.h
Gettext.h
_
#define _(MSG)
Definition Gettext.h:39
HistoryLog.h
IOStream.h
IOTools.h
Iterator.h
Json.h
LogTools.h
L_ERR
#define L_ERR(GROUP)
Definition Logger.h:114
DBG
#define DBG
Definition Logger.h:102
MIL
#define MIL
Definition Logger.h:103
ERR
#define ERR
Definition Logger.h:105
L_WAR
#define L_WAR(GROUP)
Definition Logger.h:113
WAR
#define WAR
Definition Logger.h:104
L_DBG
#define L_DBG(GROUP)
Definition Logger.h:111
INT
#define INT
Definition Logger.h:107
PluginExecutor.h
PoolItem.h
idstr
#define idstr(V)
Pool.h
ProductFileReader.h
RepoStatus.h
Repository.h
ResFilters.h
ResObjects.h
MAXRPMMESSAGELINES
#define MAXRPMMESSAGELINES
Definition RpmDb.cc:65
RpmException.h
RpmPostTransCollector.h
ShutdownLock_p.h
SolvableSpec.h
SrcPackageProvider.h
StringV.h
String.h
TargetCallbackReceiver.h
SUBST_IF
#define SUBST_IF(PAT, VAL)
TargetImpl.h
Transaction.h
Url.h
ZConfig.h
ZYppFactory.h
Target_Ptr
zypp::Arch
Architecture.
Definition Arch.h:37
zypp::Arch::asString
const std::string & asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition Arch.cc:724
zypp::Arch::compatibleWith
bool compatibleWith(const Arch &targetArch_r) const
Compatibility relation.
Definition Arch.cc:740
zypp::AutoDispose
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
zypp::AutoDispose::value
reference value() const
Reference to the Tp object.
Definition AutoDispose.h:138
zypp::AutoDispose::resetDispose
void resetDispose()
Set no dispose function.
Definition AutoDispose.h:171
zypp::Capability
A sat capability.
Definition Capability.h:63
zypp::Date
Store and operate on date (time_t).
Definition Date.h:33
zypp::Date::now
static Date now()
Return the current time.
Definition Date.h:78
zypp::Edition
Edition represents [epoch:]version[-release].
Definition Edition.h:60
zypp::Edition::version
std::string version() const
Version.
Definition Edition.cc:96
zypp::Edition::epoch_t
unsigned int epoch_t
Type of an epoch.
Definition Edition.h:63
zypp::Edition::release
std::string release() const
Release.
Definition Edition.cc:112
zypp::Edition::epoch
epoch_t epoch() const
Epoch.
Definition Edition.cc:84
zypp::Exception
Base class for Exception.
Definition Exception.h:153
zypp::Exception::remember
void remember(const Exception &old_r)
Store an other Exception as history.
Definition Exception.cc:154
zypp::ExternalProgram
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
Definition ExternalProgram.h:64
zypp::ExternalProgram::close
int close() override
Wait for the progamm to complete.
Definition ExternalProgram.cc:357
zypp::ExternalProgram::command
const std::string & command() const
The command we're executing.
Definition ExternalProgram.cc:464
zypp::ExternalProgram::Arguments
std::vector< std::string > Arguments
Definition ExternalProgram.h:68
zypp::ExternalProgram::Stderr_To_Stdout
@ Stderr_To_Stdout
Definition ExternalProgram.h:77
zypp::HistoryLog
Writing the zypp history file.
Definition HistoryLog.h:57
zypp::HistoryLog::stampCommand
void stampCommand()
Log info about the current process.
Definition HistoryLog.cc:222
zypp::HistoryLog::setRoot
static void setRoot(const Pathname &root)
Set new root directory to the default history log file path.
Definition HistoryLog.cc:163
zypp::HistoryLog::remove
void remove(const PoolItem &pi)
Log removal of a package.
Definition HistoryLog.cc:262
zypp::HistoryLog::fname
static const Pathname & fname()
Get the current log file path.
Definition HistoryLog.cc:181
zypp::HistoryLog::install
void install(const PoolItem &pi)
Log installation (or update) of a package.
Definition HistoryLog.cc:234
zypp::HistoryLog::comment
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Definition HistoryLog.cc:190
zypp::IdString
Access to the sat-pools string space.
Definition IdString.h:55
zypp::IdString::c_str
const char * c_str() const
Conversion to const char *.
Definition IdString.cc:51
zypp::IdString::asString
std::string asString() const
Conversion to std::string.
Definition IdString.h:110
zypp::Match::REGEX
@ REGEX
Regular Expression.
Definition StrMatcher.h:48
zypp::Package
Package interface.
Definition Package.h:34
zypp::Package::constPtr
TraitsType::constPtrType constPtr
Definition Package.h:39
zypp::Patch
Class representing a patch.
Definition Patch.h:38
zypp::Patch::constPtr
TraitsType::constPtrType constPtr
Definition Patch.h:43
zypp::PathInfo::LSTAT
@ LSTAT
Definition PathInfo.h:231
zypp::Pathname::assertprefix
static Pathname assertprefix(const Pathname &root_r, const Pathname &path_r)
Return path_r prefixed with root_r, unless it is already prefixed.
Definition Pathname.cc:272
zypp::PluginExecutor
Parallel execution of stateful PluginScripts.
Definition PluginExecutor.h:42
zypp::PluginExecutor::load
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
Definition PluginExecutor.cc:174
zypp::PluginExecutor::send
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
Definition PluginExecutor.cc:177
zypp::PluginFrame
Command frame for communication with PluginScript.
Definition PluginFrame.h:42
zypp::PoolItem
Combining sat::Solvable and ResStatus.
Definition PoolItem.h:51
zypp::PoolItem::resolvable
ResObject::constPtr resolvable() const
Returns the ResObject::constPtr.
Definition PoolItem.cc:227
zypp::PoolItem::status
ResStatus & status() const
Returns the current status.
Definition PoolItem.cc:212
zypp::PoolItem::buddy
sat::Solvable buddy() const
Return the buddy we share our status object with.
Definition PoolItem.cc:215
zypp::Product
Product interface.
Definition Product.h:34
zypp::Product::constPtr
TraitsType::constPtrType constPtr
Definition Product.h:39
zypp::RepoStatus
Track changing files or directories.
Definition RepoStatus.h:41
zypp::RepoStatus::fromCookieFile
static RepoStatus fromCookieFile(const Pathname &path)
Reads the status from a cookie file.
Definition RepoStatus.cc:210
zypp::RepoStatus::saveToCookieFile
void saveToCookieFile(const Pathname &path_r) const
Save the status information to a cookie file.
Definition RepoStatus.cc:224
zypp::Repository
Definition Repository.h:40
zypp::Repository::solvablesEmpty
bool solvablesEmpty() const
Whether Repository contains solvables.
Definition Repository.cc:220
zypp::Repository::solvablesEnd
SolvableIterator solvablesEnd() const
Iterator behind the last Solvable.
Definition Repository.cc:242
zypp::Repository::solvablesBegin
SolvableIterator solvablesBegin() const
Iterator to the first Solvable.
Definition Repository.cc:232
zypp::Repository::solvablesSize
size_type solvablesSize() const
Number of solvables in Repository.
Definition Repository.cc:226
zypp::Repository::addSolv
void addSolv(const Pathname &file_r)
Load Solvables from a solv-file.
Definition Repository.cc:321
zypp::Repository::eraseFromPool
void eraseFromPool()
Remove this Repository from its Pool.
Definition Repository.cc:298
zypp::ResPool
Global ResObject pool.
Definition ResPool.h:62
zypp::ResPool::instance
static ResPool instance()
Singleton ctor.
Definition ResPool.cc:38
zypp::ResPool::setHardLockQueries
void setHardLockQueries(const HardLockQueries &newLocks_r)
Set a new set of queries.
Definition ResPool.cc:104
zypp::ResPool::resolver
Resolver & resolver() const
The Resolver.
Definition ResPool.cc:62
zypp::ResPool::getRequestedLocales
const LocaleSet & getRequestedLocales() const
Return the requested locales.
Definition ResPool.cc:131
zypp::ResPool::changedPseudoInstalled
ChangedPseudoInstalled changedPseudoInstalled() const
Return all pseudo installed items whose current state differs from their initial one.
Definition ResPool.h:350
zypp::ResPool::establishedStates
EstablishedStates establishedStates() const
Factory for EstablishedStates.
Definition ResPool.cc:77
zypp::ResPool::getHardLockQueries
void getHardLockQueries(HardLockQueries &activeLocks_r)
Suggest a new set of queries based on the current selection.
Definition ResPool.cc:107
zypp::ResPool::ChangedPseudoInstalled
EstablishedStates::ChangedPseudoInstalled ChangedPseudoInstalled
Map holding pseudo installed items where current and established status differ.
Definition ResPool.h:342
zypp::ResStatus::isToBeInstalled
bool isToBeInstalled() const
Definition ResStatus.h:259
zypp::ResStatus::USER
@ USER
Definition ResStatus.h:112
zypp::ResStatus::resetTransact
bool resetTransact(TransactByValue causer_r)
Not the same as setTransact( false ).
Definition ResStatus.h:490
zypp::Resolvable::constPtr
TraitsType::constPtrType constPtr
Definition Resolvable.h:59
zypp::Resolver::getTransaction
sat::Transaction getTransaction()
Return the Transaction computed by the last solver run.
Definition Resolver.cc:77
zypp::Resolver::upgradeMode
bool upgradeMode() const
Definition Resolver.cc:100
zypp::Resolver::upgradingRepos
bool upgradingRepos() const
Whether there is at least one UpgradeRepo request pending.
Definition Resolver.cc:145
zypp::ShutdownLockCommit
Definition ShutdownLock_p.h:46
zypp::SrcPackage
SrcPackage interface.
Definition SrcPackage.h:30
zypp::SrcPackage::constPtr
TraitsType::constPtrType constPtr
Definition SrcPackage.h:36
zypp::StrMatcher
String matching (STRING|SUBSTRING|GLOB|REGEX).
Definition StrMatcher.h:298
zypp::VendorAttr
Definition of vendor equivalence.
Definition VendorAttr.h:61
zypp::ZConfig
Interim helper class to collect global options and settings.
Definition ZConfig.h:82
zypp::ZConfig::systemArchitecture
Arch systemArchitecture() const
The system architecture zypp uses.
Definition ZConfig.cc:819
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:756
zypp::ZYppCommitPolicy
Options and policies for ZYpp::commit.
Definition ZYppCommitPolicy.h:34
zypp::ZYppCommitPolicy::rpmInstFlags
ZYppCommitPolicy & rpmInstFlags(target::rpm::RpmInstFlags newFlags_r)
The default target::rpm::RpmInstFlags.
Definition ZYppCommitPolicy.cc:166
zypp::ZYppCommitPolicy::singleTransModeEnabled
bool singleTransModeEnabled() const
Whether the single_rpmtrans backend is enabled (or the classic_rpmtrans).
Definition ZYppCommitPolicy.cc:202
zypp::ZYppCommitPolicy::rpmExcludeDocs
ZYppCommitPolicy & rpmExcludeDocs(bool yesNo_r)
Use rpm option –excludedocs (default: false).
Definition ZYppCommitPolicy.cc:172
zypp::ZYppCommitPolicy::dryRun
ZYppCommitPolicy & dryRun(bool yesNo_r)
Set dry run (default: false).
Definition ZYppCommitPolicy.cc:154
zypp::ZYppCommitPolicy::restrictToMedia
ZYppCommitPolicy & restrictToMedia(unsigned mediaNr_r)
Restrict commit to media 1.
Definition ZYppCommitPolicy.cc:147
zypp::ZYppCommitPolicy::downloadMode
ZYppCommitPolicy & downloadMode(DownloadMode val_r)
Commit download policy to use.
Definition ZYppCommitPolicy.cc:160
zypp::ZYppCommitPolicy::allMedia
ZYppCommitPolicy & allMedia()
Process all media (default).
Definition ZYppCommitPolicy.h:48
zypp::ZYppCommitPolicy::rpmNoSignature
ZYppCommitPolicy & rpmNoSignature(bool yesNo_r)
Use rpm option –nosignature (default: false).
Definition ZYppCommitPolicy.cc:169
zypp::ZYppCommitResult
Result returned from ZYpp::commit.
Definition ZYppCommitResult.h:64
zypp::ZYppCommitResult::rTransactionStepList
TransactionStepList & rTransactionStepList()
Manipulate transactionStepList.
Definition ZYppCommitResult.cc:93
zypp::ZYppCommitResult::setSingleTransactionMode
void setSingleTransactionMode(bool yesno_r)
Definition ZYppCommitResult.cc:81
zypp::ZYppCommitResult::TransactionStepList
std::vector< sat::Transaction::Step > TransactionStepList
Definition ZYppCommitResult.h:66
zypp::ZYppCommitResult::transaction
const sat::Transaction & transaction() const
The full transaction list.
Definition ZYppCommitResult.cc:84
zypp::ZYppCommitResult::rTransaction
sat::Transaction & rTransaction()
Manipulate transaction.
Definition ZYppCommitResult.cc:87
zypp::ZYppFactory::lockfileDir
static zypp::Pathname lockfileDir()
Definition ZYppFactory.cc:467
zypp::callback::UserData
Typesafe passing of user data via callbacks.
Definition UserData.h:40
zypp::callback::UserData::set
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
Definition UserData.h:119
zypp::externalprogram::ExternalDataSource::receiveLine
std::string receiveLine()
Read one line from the input stream.
Definition ExternalDataSource.cc:115
zypp::filesystem::PathInfo
Wrapper class for stat/lstat.
Definition PathInfo.h:226
zypp::filesystem::PathInfo::isExist
bool isExist() const
Return whether valid stat info exists.
Definition PathInfo.h:286
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:48
zypp::filesystem::Pathname::dirname
Pathname dirname() const
Return all but the last component od this path.
Definition Pathname.h:133
zypp::filesystem::Pathname::c_str
const char * c_str() const
String representation.
Definition Pathname.h:113
zypp::filesystem::Pathname::asString
const std::string & asString() const
String representation.
Definition Pathname.h:94
zypp::filesystem::Pathname::empty
bool empty() const
Test for an empty path.
Definition Pathname.h:117
zypp::filesystem::TmpFile
Provide a new empty temporary file and delete it when no longer needed.
Definition TmpPath.h:118
zypp::filesystem::TmpFile::makeSibling
static TmpFile makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition TmpPath.cc:182
zypp::filesystem::TmpPath::path
Pathname path() const
Definition TmpPath.cc:124
zypp::json::Array
Definition JsonValue.h:32
zypp::json::Array::add
void add(Value val_r)
Push JSON Value to Array.
Definition JsonValue.cc:20
zypp::json::Object
Definition JsonValue.h:99
zypp::json::Object::add
void add(String key_r, Value val_r)
Add key/value pair.
Definition JsonValue.cc:62
zypp::json::Value
Definition JsonValue.h:173
zypp::parser::ProductFileData
Data returned by ProductFileReader.
Definition ProductFileReader.h:42
zypp::parser::ProductFileData::empty
bool empty() const
Whether this is an empty object without valid data.
Definition ProductFileReader.h:49
zypp::parser::ProductFileData::summary
std::string summary() const
Definition ProductFileReader.cc:96
zypp::parser::ProductFileData::shortName
std::string shortName() const
Definition ProductFileReader.cc:95
zypp::parser::ProductFileReader::scanFile
static ProductFileData scanFile(const Pathname &file_r)
Parse one file (or symlink) and return the ProductFileData parsed.
Definition ProductFileReader.cc:272
zypp::repo::RepoMediaAccess
Provides files from different repos.
Definition RepoProvideFile.h:73
zypp::repo::SrcPackageProvider
Definition SrcPackageProvider.h:39
zypp::repo::SrcPackageProvider::provideSrcPackage
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r) const
Provide SrcPackage in a local file.
Definition SrcPackageProvider.cc:36
zypp::sat::Pool
Global sat-pool.
Definition Pool.h:47
zypp::sat::Pool::setAutoInstalled
void setAutoInstalled(const Queue &autoInstalled_r)
Set ident list of all autoinstalled solvables.
Definition Pool.cc:265
zypp::sat::Pool::rootDir
Pathname rootDir() const
Get rootdir (for file conflicts check).
Definition Pool.cc:64
zypp::sat::Pool::instance
static Pool instance()
Singleton ctor.
Definition Pool.h:55
zypp::sat::Pool::systemRepoAlias
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
Definition Pool.cc:46
zypp::sat::Pool::setNeedrebootSpec
void setNeedrebootSpec(sat::SolvableSpec needrebootSpec_r)
Solvables which should trigger the reboot-needed hint if installed/updated.
Definition Pool.cc:267
zypp::sat::Pool::systemRepo
Repository systemRepo()
Return the system repository, create it if missing.
Definition Pool.cc:178
zypp::sat::Pool::initRequestedLocales
void initRequestedLocales(const LocaleSet &locales_r)
Start tracking changes based on this locales_r.
Definition Pool.cc:251
zypp::sat::Queue::value_type
detail::IdType value_type
Definition Queue.h:39
zypp::sat::Queue::push
void push(value_type val_r)
Push a value to the end off the Queue.
Definition Queue.cc:103
zypp::sat::Solvable
A Solvable object within the sat Pool.
Definition Solvable.h:54
zypp::sat::Transaction::Step
A single step within a Transaction.
Definition Transaction.h:219
zypp::sat::Transaction::Step::arch
Arch arch() const
Definition Transaction.cc:405
zypp::sat::Transaction::Step::ident
IdString ident() const
Definition Transaction.cc:399
zypp::sat::Transaction::Step::stepType
StepType stepType() const
Type of action to perform in this step.
Definition Transaction.cc:390
zypp::sat::Transaction::Step::stepStage
StepStage stepStage() const
Step action result.
Definition Transaction.cc:393
zypp::sat::Transaction::Step::satSolvable
Solvable satSolvable() const
Return the corresponding Solvable.
Definition Transaction.h:243
zypp::sat::Transaction::Step::edition
Edition edition() const
Definition Transaction.cc:402
zypp::sat::Transaction
Libsolv transaction wrapper.
Definition Transaction.h:52
zypp::sat::Transaction::end
const_iterator end() const
Iterator behind the last TransactionStep.
Definition Transaction.cc:345
zypp::sat::Transaction::autoInstalled
StringQueue autoInstalled() const
Return the ident strings of all packages that would be auto-installed after the transaction is run.
Definition Transaction.cc:360
zypp::sat::Transaction::begin
const_iterator begin() const
Iterator to the first TransactionStep.
Definition Transaction.cc:339
zypp::sat::Transaction::order
bool order()
Order transaction steps for commit.
Definition Transaction.cc:330
zypp::sat::Transaction::TRANSACTION_MULTIINSTALL
@ TRANSACTION_MULTIINSTALL
[M] Install(multiversion) item (
Definition Transaction.h:67
zypp::sat::Transaction::TRANSACTION_INSTALL
@ TRANSACTION_INSTALL
[+] Install(update) item
Definition Transaction.h:66
zypp::sat::Transaction::TRANSACTION_IGNORE
@ TRANSACTION_IGNORE
[ ] Nothing (includes implicit deletes due to obsoletes and non-package actions)
Definition Transaction.h:64
zypp::sat::Transaction::TRANSACTION_ERASE
@ TRANSACTION_ERASE
[-] Delete item
Definition Transaction.h:65
zypp::sat::Transaction::STEP_DONE
@ STEP_DONE
[OK] success
Definition Transaction.h:74
zypp::sat::Transaction::STEP_TODO
@ STEP_TODO
[__] unprocessed
Definition Transaction.h:73
zypp::sat::Transaction::STEP_ERROR
@ STEP_ERROR
[**] error
Definition Transaction.h:75
zypp::sat::detail::PoolImpl::multiversionSpecChanged
void multiversionSpecChanged()
Definition PoolImpl.cc:625
zypp::target::CommitPackageCache
Target::commit helper optimizing package provision.
Definition CommitPackageCache.h:59
zypp::target::CommitPackageCache::setCommitList
void setCommitList(std::vector< sat::Solvable > commitList_r)
Download(commit) sequence of solvables to compute read ahead.
Definition CommitPackageCache.cc:138
zypp::target::CommitPackageCache::preloaded
bool preloaded() const
Whether preloaded hint is set.
Definition CommitPackageCache.cc:144
zypp::target::CommitPackageCache::get
ManagedFile get(const PoolItem &citem_r)
Provide a package.
Definition CommitPackageCache.cc:141
zypp::target::HardLocksFile::Data
pool::PoolTraits::HardLockQueries Data
Definition HardLocksFile.h:42
zypp::target::RequestedLocalesFile
Save and restore locale set from file.
Definition RequestedLocalesFile.h:37
zypp::target::RequestedLocalesFile::locales
const LocaleSet & locales() const
Return the loacale set.
Definition RequestedLocalesFile.h:54
zypp::target::RpmInstallPackageReceiver
Definition TargetCallbackReceiver.h:27
zypp::target::RpmInstallPackageReceiver::tryLevel
void tryLevel(target::rpm::InstallResolvableReport::RpmLevel level_r)
Definition TargetCallbackReceiver.cc:110
zypp::target::RpmInstallPackageReceiver::aborted
bool aborted() const
Definition TargetCallbackReceiver.h:51
zypp::target::RpmPostTransCollector
Extract and remember posttrans scripts for later execution.
Definition RpmPostTransCollector.h:41
zypp::target::RpmPostTransCollector::executeScripts
void executeScripts(rpm::RpmDb &rpm_r, const IdStringSet &obsoletedPackages_r)
Execute the remembered scripts and/or or dump_posttrans lines.
Definition RpmPostTransCollector.cc:426
zypp::target::RpmPostTransCollector::discardScripts
void discardScripts()
Discard all remembered scripts and/or or dump_posttrans lines.
Definition RpmPostTransCollector.cc:429
zypp::target::RpmRemovePackageReceiver
Definition TargetCallbackReceiver.h:74
zypp::target::RpmRemovePackageReceiver::aborted
bool aborted() const
Returns true if removing is aborted during progress.
Definition TargetCallbackReceiver.h:104
zypp::target::SolvIdentFile::Data
std::unordered_set< IdString > Data
Definition SolvIdentFile.h:38
zypp::target::TargetAbortedException
Definition TargetException.h:52
zypp::target::TargetImpl
Base class for concrete Target implementations.
Definition TargetImpl.h:54
zypp::target::TargetImpl::targetDistributionRelease
std::string targetDistributionRelease() const
This is register.release attribute of the installed base product.
Definition TargetImpl.cc:3051
zypp::target::TargetImpl::clearCache
void clearCache()
Definition TargetImpl.cc:1107
zypp::target::TargetImpl::vendorAttr
const VendorAttr & vendorAttr() const
The targets current vendor equivalence settings.
Definition TargetImpl.h:199
zypp::target::TargetImpl::targetDistribution
std::string targetDistribution() const
This is register.target attribute of the installed base product.
Definition TargetImpl.cc:3045
zypp::target::TargetImpl::PoolItemList
std::list< PoolItem > PoolItemList
list of pool items
Definition TargetImpl.h:59
zypp::target::TargetImpl::requestedLocales
LocaleSet requestedLocales() const
Languages to be supported by the system.
Definition TargetImpl.h:155
zypp::target::TargetImpl::updateAutoInstalled
void updateAutoInstalled()
Update the database of autoinstalled packages.
Definition TargetImpl.cc:3036
zypp::target::TargetImpl::provideSrcPackage
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Provides a source package on the Target.
Definition TargetImpl.cc:3166
zypp::target::TargetImpl::_root
Pathname _root
Path to the target.
Definition TargetImpl.h:222
zypp::target::TargetImpl::_requestedLocalesFile
RequestedLocalesFile _requestedLocalesFile
Requested Locales database.
Definition TargetImpl.h:226
zypp::target::TargetImpl::createLastDistributionFlavorCache
void createLastDistributionFlavorCache() const
generates a cache of the last product flavor
Definition TargetImpl.cc:1053
zypp::target::TargetImpl::_tmpSolvfilesPath
Pathname _tmpSolvfilesPath
Definition TargetImpl.h:99
zypp::target::TargetImpl::_distributionVersion
std::string _distributionVersion
Cache distributionVersion.
Definition TargetImpl.h:232
zypp::target::TargetImpl::_rpm
rpm::RpmDb _rpm
RPM database.
Definition TargetImpl.h:224
zypp::target::TargetImpl::~TargetImpl
~TargetImpl() override
Dtor.
Definition TargetImpl.cc:1089
zypp::target::TargetImpl::buildCache
bool buildCache()
Definition TargetImpl.cc:1113
zypp::target::TargetImpl::rpm
rpm::RpmDb & rpm()
The RPM database.
Definition TargetImpl.cc:2952
zypp::target::TargetImpl::solvfilesPath
Pathname solvfilesPath() const
The solv file location actually in use (default or temp).
Definition TargetImpl.h:92
zypp::target::TargetImpl::distributionVersion
std::string distributionVersion() const
This is version attribute of the installed base product.
Definition TargetImpl.cc:3081
zypp::target::TargetImpl::createAnonymousId
void createAnonymousId() const
generates the unique anonymous id which is called when creating the target
Definition TargetImpl.cc:1031
zypp::target::TargetImpl::unload
void unload()
Definition TargetImpl.cc:1267
zypp::target::TargetImpl::_autoInstalledFile
SolvIdentFile _autoInstalledFile
user/auto installed database
Definition TargetImpl.h:228
zypp::target::TargetImpl::baseProduct
Product::constPtr baseProduct() const
returns the target base installed product, also known as the distribution or platform.
Definition TargetImpl.cc:3015
zypp::target::TargetImpl::distributionLabel
Target::DistributionLabel distributionLabel() const
This is shortName and summary attribute of the installed base product.
Definition TargetImpl.cc:3063
zypp::target::TargetImpl::providesFile
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::...
Definition TargetImpl.cc:2957
zypp::target::TargetImpl::_hardLocksFile
HardLocksFile _hardLocksFile
Hard-Locks database.
Definition TargetImpl.h:230
zypp::target::TargetImpl::root
Pathname root() const
The root set for this target.
Definition TargetImpl.h:116
zypp::target::TargetImpl::load
void load(bool force=true)
Definition TargetImpl.cc:1274
zypp::target::TargetImpl::distributionFlavor
std::string distributionFlavor() const
This is flavor attribute of the installed base product but does not require the target to be loaded a...
Definition TargetImpl.cc:3110
zypp::target::TargetImpl::commitInSingleTransaction
void commitInSingleTransaction(const ZYppCommitPolicy &policy_r, CommitPackageCache &packageCache_r, ZYppCommitResult &result_r)
Commit ordered changes (internal helper).
Definition TargetImpl.cc:2077
zypp::target::TargetImpl::reload
void reload()
Definition TargetImpl.cc:1262
zypp::target::TargetImpl::installSrcPackage
void installSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
Definition TargetImpl.cc:3155
zypp::target::TargetImpl::commit
ZYppCommitResult commit(ResPool pool_r, const ZYppCommitPolicy &policy_r)
Commit changes in the pool.
Definition TargetImpl.cc:1410
zypp::target::TargetImpl::_vendorAttr
VendorAttr _vendorAttr
vendor equivalence settings.
Definition TargetImpl.h:234
zypp::target::TargetImpl::home
Pathname home() const
The directory to store things.
Definition TargetImpl.h:120
zypp::target::TargetImpl::commitFindFileConflicts
void commitFindFileConflicts(const ZYppCommitPolicy &policy_r, ZYppCommitResult &result_r)
Commit helper checking for file conflicts after download.
Definition TargetImpl.commitFindFileConflicts.cc:122
zypp::target::TargetImpl::defaultSolvfilesPath
Pathname defaultSolvfilesPath() const
The systems default solv file location.
Definition TargetImpl.cc:1102
zypp::target::TargetImpl::anonymousUniqueId
std::string anonymousUniqueId() const
anonymous unique id
Definition TargetImpl.cc:3136
zypp::target::TargetImpl::TargetImpl
TargetImpl(const Pathname &root_r="/", bool doRebuild_r=false)
Ctor.
Definition TargetImpl.cc:961
zypp::target::TargetImpl::solvfilesPathIsTemp
bool solvfilesPathIsTemp() const
Whether we're using a temp.
Definition TargetImpl.h:96
zypp::target::TargetImpl::targetDistributionFlavor
std::string targetDistributionFlavor() const
This is register.flavor attribute of the installed base product.
Definition TargetImpl.cc:3057
zypp::target::rpm::RpmDbOpenException
Definition RpmException.h:163
zypp::target::rpm::RpmDb
Interface to the rpm program.
Definition RpmDb.h:51
zypp::target::rpm::RpmDb::installPackage
void installPackage(const Pathname &filename, RpmInstFlags flags=RPMINST_NONE)
install rpm package
Definition RpmDb.cc:1652
zypp::target::rpm::RpmDb::root
const Pathname & root() const
Definition RpmDb.h:109
zypp::target::rpm::RpmDb::removePackage
void removePackage(const std::string &name_r, RpmInstFlags flags=RPMINST_NONE)
remove rpm package
Definition RpmDb.cc:1854
zypp::target::rpm::RpmDb::dbPath
const Pathname & dbPath() const
Definition RpmDb.h:117
zypp::target::rpm::RpmInitException
Definition RpmException.h:145
zypp::target::rpm::RpmSubprocessException
Definition RpmException.h:130
zypp::target::rpm::RpmTransactionFailedException
Definition RpmException.h:244
zypp::target::rpm::librpmDb::db_const_iterator
Subclass to retrieve rpm database content.
Definition librpmDb.h:198
zypp::target::rpm::librpmDb::db_const_iterator::findByProvides
bool findByProvides(const std::string &tag_r)
Reset to iterate all packages that provide a certain tag.
Definition librpmDb.cc:421
zyppng::AsyncDataSource::create
static Ptr create()
Definition asyncdatasource.cpp:146
zyppng::EventLoop::create
static Ptr create(GMainContext *ctx=nullptr)
Definition eventloop_glib.cc:29
zyppng::IODevice::sigChannelReadyRead
SignalProxy< void(uint)> sigChannelReadyRead()
Definition iodevice.cc:373
zyppng::Process::create
static Ptr create()
Definition process.cpp:49
zyppng::Process::StdErr
@ StdErr
Definition process.h:49
zyppng::Process::StdOut
@ StdOut
Definition process.h:48
zyppng::Process::sigFinished
SignalProxy< void(int)> sigFinished()
Definition process.cpp:294
zyppng::StompFrameStream::sigMessageReceived
SignalProxy< void()> sigMessageReceived()
Definition stompframestream.cc:310
zyppng::StompFrameStream::create
static Ptr create(IODevice::Ptr iostr)
Definition stompframestream.h:119
commitpackagepreloader_p.h
librpmDb.h
linuxhelpers_p.h
form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
std
Definition ansi.h:855
ztui::UNKNOWN
@ UNKNOWN
Definition richtext.cc:49
zypp::base
Definition Random.cc:7
zypp::env
Namespace intended to collect all environment variables we use.
Definition RepoVariables.cc:34
zypp::env::TRANSACTIONAL_UPDATE
bool TRANSACTIONAL_UPDATE()
Definition TargetImpl.cc:86
zypp::filesystem::chmod
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
Definition PathInfo.cc:1111
zypp::filesystem::symlink
int symlink(const Pathname &oldpath, const Pathname &newpath)
Like 'symlink'.
Definition PathInfo.cc:874
zypp::filesystem::matchNoDots
const StrMatcher & matchNoDots()
Convenience returning StrMatcher( "[^.]*", Match::GLOB ).
Definition PathInfo.cc:26
zypp::filesystem::assert_file
int assert_file(const Pathname &path, unsigned mode)
Create an empty file if it does not yet exist.
Definition PathInfo.cc:1205
zypp::filesystem::recursive_rmdir
int recursive_rmdir(const Pathname &path)
Like 'rm -r DIR'.
Definition PathInfo.cc:431
zypp::filesystem::unlink
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:719
zypp::filesystem::readdir
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition PathInfo.cc:624
zypp::filesystem::dirForEach
int dirForEach(const Pathname &dir_r, const StrMatcher &matcher_r, function< bool(const Pathname &, const char *const)> fnc_r)
Definition PathInfo.cc:32
zypp::filesystem::addmod
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
Definition PathInfo.cc:1123
zypp::filesystem::assert_dir
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:338
zypp::filesystem::readlink
int readlink(const Pathname &symlink_r, Pathname &target_r)
Like 'readlink'.
Definition PathInfo.cc:943
zypp::filesystem::md5sum
std::string md5sum(const Pathname &file)
Compute a files md5sum.
Definition PathInfo.cc:1043
zypp::filesystem::rename
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
Definition PathInfo.cc:761
zypp::filesystem::touch
int touch(const Pathname &path)
Change file's modification and access times.
Definition PathInfo.cc:1256
zypp::iostr::getline
std::string getline(std::istream &str)
Read one line from stream.
Definition IOStream.cc:33
zypp::json
Definition TargetImpl.cc:152
zypp::json::toJSON
json::Value toJSON(const sat::Transaction::Step &step_r)
See COMMITBEGIN (added in v1) on page Commit plugin for the specs.
Definition TargetImpl.cc:157
zypp::pool
Definition ByIdent.h:24
zypp::sat::empty
bool empty() const
Whether neither idents nor provides are set.
zypp::sat::StringQueue
Queue StringQueue
Queue with String ids.
Definition Queue.h:28
zypp::sat::updateSolvFileIndex
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
Definition Pool.cc:286
zypp::str::hasPrefix
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition String.h:1097
zypp::str::toLower
std::string toLower(const std::string &s)
Return lowercase version of s.
Definition String.cc:180
zypp::str::startsWith
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
Definition String.h:1155
zypp::str::endsWith
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
Definition String.h:1162
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
zypp::str::strToBool
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition String.h:500
zypp::str::splitEscaped
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.
Definition String.h:665
zypp::str::trim
std::string trim(const std::string &s, const Trim trim_r)
Definition String.cc:226
zypp::target::rpm::RPMINST_NOSIGNATURE
@ RPMINST_NOSIGNATURE
Definition RpmFlags.h:47
zypp::target::rpm::RPMINST_ALLOWUNTRUSTED
@ RPMINST_ALLOWUNTRUSTED
Definition RpmFlags.h:53
zypp::target::rpm::RPMINST_NODEPS
@ RPMINST_NODEPS
Definition RpmFlags.h:43
zypp::target::rpm::RPMINST_JUSTDB
@ RPMINST_JUSTDB
Definition RpmFlags.h:45
zypp::target::rpm::RPMINST_FORCE
@ RPMINST_FORCE
Definition RpmFlags.h:42
zypp::target::rpm::RPMINST_TEST
@ RPMINST_TEST
Definition RpmFlags.h:49
zypp::target::rpm::RPMINST_NODIGEST
@ RPMINST_NODIGEST
Definition RpmFlags.h:46
zypp::target::rpm::RPMINST_NOUPGRADE
@ RPMINST_NOUPGRADE
Definition RpmFlags.h:48
zypp::target::rpm::RPMINST_EXCLUDEDOCS
@ RPMINST_EXCLUDEDOCS
Definition RpmFlags.h:40
zypp::target
Definition KeyRing.h:325
zypp::target::XRunUpdateMessages
void XRunUpdateMessages(const Pathname &root_r, const Pathname &messagesPath_r, const std::vector< sat::Solvable > &checkPackages_r, ZYppCommitResult &result_r)
Definition TargetImpl.cc:946
zypp::target::rpmDbStateHash
std::string rpmDbStateHash(const Pathname &root_r)
Definition TargetImpl.cc:108
zypp::target::writeUpgradeTestcase
void writeUpgradeTestcase()
Definition TargetImpl.cc:500
zypp::target::fileMissing
static bool fileMissing(const Pathname &pathname)
helper functor
Definition TargetImpl.cc:1026
zypp::target::updateFileContent
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...
Definition TargetImpl.cc:991
zypp::target::rpmDbRepoStatus
RepoStatus rpmDbRepoStatus(const Pathname &root_r)
Definition TargetImpl.cc:126
zypp::target::generateRandomId
static std::string generateRandomId()
generates a random id using uuidgen
Definition TargetImpl.cc:980
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
zypp::LocaleSet
std::unordered_set< Locale > LocaleSet
Definition Locale.h:29
zypp::getZYpp
ZYpp::Ptr getZYpp()
relates: ZYppFactory Convenience to get the Pointer to the ZYpp instance.
Definition ZYppFactory.h:77
zypp::ManagedFile
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
zypp::UpdateNotifications
std::list< UpdateNotificationFile > UpdateNotifications
Definition ZYppCommitResult.h:48
zypp::IdStringSet
std::unordered_set< IdString > IdStringSet
Definition IdString.h:37
zypp::make
ResTraits< TRes >::PtrType make(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
Definition ResObject.h:118
zypp::makeResObject
ResObject::Ptr makeResObject(const sat::Solvable &solvable_r)
Create ResObject from sat::Solvable.
Definition ResObject.cc:43
zypp::asString
std::string asString(const Patch::Category &obj)
relates: Patch::Category string representation.
Definition Patch.cc:122
zypp::asKind
ResTraits< TRes >::PtrType asKind(const sat::Solvable &solvable_r)
Directly create a certain kind of ResObject from sat::Solvable.
Definition ResObject.h:127
zypp::TrueBool
DefaultIntegral< bool, true > TrueBool
relates: DefaultIntegral true initialized bool
Definition defaultintegral.h:88
zypp::DownloadInHeaps
@ DownloadInHeaps
Definition DownloadMode.h:31
zypp::DownloadOnly
@ DownloadOnly
Definition DownloadMode.h:27
zypp::DownloadAsNeeded
@ DownloadAsNeeded
Definition DownloadMode.h:34
zypp::DownloadInAdvance
@ DownloadInAdvance
Definition DownloadMode.h:29
zypp::DownloadDefault
@ DownloadDefault
libzypp will decide what to do.
Definition DownloadMode.h:26
zyppng::IdString
zypp::IdString IdString
Definition idstring.h:16
zyppng::UserData
zypp::callback::UserData UserData
Definition userrequest.h:18
PoolImpl.h
stompframestream.h
zypp::Deferred
Definition AutoDispose.h:279
zypp::JobReport::error
static bool error(const std::string &msg_r, const UserData &userData_r=UserData())
send error text
Definition ZYppCallbacks.h:1107
zypp::Target::DistributionLabel
Definition Target.h:168
zypp::Target::DistributionLabel::shortName
std::string shortName
Definition Target.h:168
zypp::Target::DistributionLabel::summary
std::string summary
Definition Target.h:168
zypp::callback::ReceiveReport::connect
void connect()
Definition Callback.h:183
zypp::callback::SendReport
Definition Callback.h:237
zypp::callback::SendReport::connected
static bool connected()
Definition Callback.h:251
zypp::env::ScopedSet
Temporarily set/unset an environment variable.
Definition Env.h:45
zypp::functor::Constant
Definition Functional.h:59
zypp::sat::SolvableType::satSolvable
Solvable satSolvable() const
Return the corresponding sat::Solvable.
Definition SolvableType.h:57
zypp::sat::SolvableType::isNeedreboot
bool isNeedreboot() const
Definition SolvableType.h:83
zypp::sat::detail::PoolMember::myPool
static PoolImpl & myPool()
Definition PoolMember.cc:41
zypp::sat::detail::PoolMember::poolValid
static bool poolValid()
Definition PoolMember.cc:48
zypp::str::Format
Convenient building of std::string with boost::format.
Definition String.h:254
zypp::target::PatchScriptReport::ABORT
@ ABORT
Definition ZYppCallbacks.h:523
zypp::target::PatchScriptReport::RETRY
@ RETRY
Definition ZYppCallbacks.h:524
zypp::target::PatchScriptReport::IGNORE
@ IGNORE
Definition ZYppCallbacks.h:525
zypp::target::PatchScriptReport::OUTPUT
@ OUTPUT
Definition ZYppCallbacks.h:521
zypp::target::SendSingleTransReport
Convenience SendReport<rpm::SingleTransReport> wrapper.
Definition TargetImpl.cc:2039
zypp::target::SendSingleTransReport::report
void report(const callback::UserData &userData_r)
Definition TargetImpl.cc:2073
zypp::target::SendSingleTransReport::sendLoglineRpm
void sendLoglineRpm(const std::string &line_r, unsigned rpmlevel_r)
Convenience to send a contentLogline translating a rpm loglevel.
Definition TargetImpl.cc:2049
zypp::target::SendSingleTransReport::sendLogline
void sendLogline(const std::string &line_r, ReportType::loglevel level_r=ReportType::loglevel::msg)
Convenience to send a contentLogline.
Definition TargetImpl.cc:2041
zypp::target::rpm::CleanupPackageReportSA::NO_ERROR
@ NO_ERROR
Definition ZYppCallbacks.h:884
zypp::target::rpm::CommitScriptReportSA::CRITICAL
@ CRITICAL
Definition ZYppCallbacks.h:916
zypp::target::rpm::CommitScriptReportSA::WARN
@ WARN
Definition ZYppCallbacks.h:915
zypp::target::rpm::CommitScriptReportSA::NO_ERROR
@ NO_ERROR
Definition ZYppCallbacks.h:914
zypp::target::rpm::InstallResolvableReportSA::INVALID
@ INVALID
Definition ZYppCallbacks.h:819
zypp::target::rpm::InstallResolvableReportSA::NO_ERROR
@ NO_ERROR
Definition ZYppCallbacks.h:816
zypp::target::rpm::InstallResolvableReport::Error
Error
Definition ZYppCallbacks.h:599
zypp::target::rpm::InstallResolvableReport::RPM_NODEPS_FORCE
@ RPM_NODEPS_FORCE
only this one used
Definition ZYppCallbacks.h:611
zypp::target::rpm::InstallResolvableReport::RPM
@ RPM
Definition ZYppCallbacks.h:609
zypp::target::rpm::RemoveResolvableReportSA::INVALID
@ INVALID
Definition ZYppCallbacks.h:854
zypp::target::rpm::RemoveResolvableReportSA::NO_ERROR
@ NO_ERROR
Definition ZYppCallbacks.h:851
zypp::target::rpm::RemoveResolvableReport::Error
Error
Definition ZYppCallbacks.h:653
zypp::target::rpm::TransactionReportSA::NO_ERROR
@ NO_ERROR
Definition ZYppCallbacks.h:784
zyppng::Pipe::create
static std::optional< Pipe > create(int flags=0)
Definition linuxhelpers.cc:71
IMPL_PTR_TYPE
#define IMPL_PTR_TYPE(NAME)
Definition ReferenceCounted.h:137
PathInfo.h
TmpPath.h