14#include <zypp/base/LogTools.h>
15#include <zypp/base/NonCopyable.h>
16#include <zypp/base/Gettext.h>
17#include <zypp/base/Regex.h>
18#include <zypp/base/IOStream.h>
22#include <zypp/TmpPath.h>
23#include <zypp/PathInfo.h>
26#include <zypp/ExternalProgram.h>
33#undef ZYPP_BASE_LOGGER_LOGGROUP
34#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::posttrans"
52 using ScriptList = std::list< std::pair<std::string,std::string> >;
95 std::ofstream out( script.
path().
c_str() );
96 out <<
"#! " << pkg->tag_posttransprog() << endl
97 << pkg->tag_posttrans() << endl;
101 MIL <<
"COLLECT posttrans: '" <<
PathInfo( script.
path() ) <<
"' for package: '" << pkg->tag_name() <<
"'" << endl;
115 if ( runposttrans_r.empty() ) {
117 MIL <<
"LOST dump_posttrans support" << endl;
128 MIL <<
"COLLECT dump_posttrans to '" <<
_dumpfile->_dumpfile << endl;
131 std::ofstream out(
_dumpfile->_dumpfile.c_str(), std::ios_base::app );
132 for (
const auto & s : runposttrans_r ) {
135 _dumpfile->_numscripts += runposttrans_r.size();
136 MIL <<
"COLLECT " << runposttrans_r.size() <<
" dump_posttrans lines" << endl;
153 MIL <<
"Extract missing %posttrans scripts and prepend them to the scripts." << endl;
156 std::optional<ScriptList> savedscripts;
158 savedscripts = std::move(*
_scripts);
164 if ( it.findPackage( n_r, Edition( v_r, r_r ) ) && headerHasPosttrans( *it ) )
165 collectScriptFromHeader( *it );
169 if ( savedscripts ) {
173 _scripts = std::move(*savedscripts);
194 std::string scriptProgressName {
_(
"Running post-transaction scripts") };
196 str::Format fmtScriptProgressRun {
_(
"Running %1% script") };
199 std::string sendRipoff;
204 auto startNewScript = [&] (
const std::string & scriptident_r ) ->
void {
206 sendRipoff = fmtRipoff % scriptident_r;
207 scriptProgress.
name( fmtScriptProgressRun % scriptident_r );
208 scriptProgress.
incr();
212 auto sendScriptOutput = [&] (
const std::string & line_r ) ->
void {
214 if ( not sendRipoff.empty() ) {
215 historylog.
comment( sendRipoff,
true );
227 scriptProgress.
name( scriptProgressName );
228 scriptProgress.
toMin();
234 str::Format fmtScriptFailedMsg {
"warning: %%posttrans(%1%) scriptlet failed, exit status %2%\n" };
239 const auto &scriptPair =
_scripts->front();
240 const std::string & script = scriptPair.first;
241 const std::string & pkgident( script.substr( 0, script.size()-6 ) );
242 startNewScript( fmtPosttrans % pkgident );
246 for ( it.
findByName( scriptPair.second ); *it; ++it )
249 MIL <<
"EXECUTE posttrans: " << script <<
" with argument: " << npkgs << endl;
252 (noRootScriptDir/script).asString(),
258 sendScriptOutput( line );
263 int ret = prog.
close();
266 std::string msg { fmtScriptFailedMsg % pkgident % ret };
268 sendScriptOutput( msg );
278 if ( str::startsWith( line_r,
"RIPOFF:" ) )
279 startNewScript( line_r.substr( 7 ) );
281 sendScriptOutput( line_r );
290 scriptProgress.
name( scriptProgressName );
292 scriptProgress.
toMax();
309 msg <<
"%posttrans scripts skipped while aborting:" << endl;
310 for (
const auto & script : *
_scripts )
312 WAR <<
"UNEXECUTED posttrans: " << script.first << endl;
313 const std::string & pkgident( script.first.substr( 0, script.first.size()-6 ) );
314 msg <<
" " << pkgident <<
"\n";
320 msg <<
"%posttrans and %transfiletrigger scripts are not executed when aborting!" << endl;
325 historylog.
comment( msg,
true );
343 std::string prog( pkg_r->tag_posttransprog() );
344 if ( not prog.empty() && prog !=
"<lua>" )
363 WAR <<
"Unexpectedly this is no package: " << rpmPackage_r << endl;
373 static const str::regex rxInstalled {
"^dump_posttrans: +install +[0-9]+ +(.+)-([^-]+)-([^-]+)\\.([^.]+)" };
377 consume_r( what[1], what[2], what[3], what[4] );
395 {
return str <<
"RpmPostTransCollector::Impl"; }
399 {
return str << obj; }
408 : _pimpl( new
Impl( root_r ) )
415 {
return _pimpl->hasPosttransScript( rpmPackage_r ); }
418 {
_pimpl->collectPosttransInfo( rpmPackage_r, runposttrans_r ); }
421 {
_pimpl->collectPosttransInfo( runposttrans_r ); }
424 {
_pimpl->executeScripts( rpm_r ); }
427 {
return _pimpl->discardScripts(); }
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
std::vector< std::string > Arguments
int close()
Wait for the progamm to complete.
Writing the zypp history file.
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Maintain [min,max] and counter (value) for progress counting.
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
bool toMax()
Set counter value to current max value (unless no range).
void name(const std::string &name_r)
Set counter name.
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
bool incr(value_type val_r=1)
Increment counter value (default by 1).
bool toMin()
Set counter value to current min value.
static ZConfig & instance()
Singleton ctor.
void erase(const std::string &key_r)
Remove key from data.
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
std::string receiveLine()
Read one line from the input stream.
Wrapper class for stat/lstat.
const char * c_str() const
String representation.
std::string basename() const
Return the last component of this path.
Provide a new empty temporary directory and recursively delete it when no longer needed.
Provide a new empty temporary file and delete it when no longer needed.
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Regular expression match result.
RpmPostTransCollector implementation.
UserDataJobReport _myJobReport
JobReport with ContentType "cmdout/%posttrans".
bool headerHasPosttrans(rpm::RpmHeader::constPtr pkg_r) const
Return whether RpmHeader has a posttrans.
void discardScripts()
Discard all remembered scrips.
void collectPosttransInfo(const std::vector< std::string > &runposttrans_r)
void recallFromDumpfile(const Pathname &dumpfile_r, std::function< void(std::string, std::string, std::string, std::string)> consume_r)
Retrieve "dump_posttrans: install" lines from dumpfile_r and pass n,v,r,a to the consumer_r.
rpm::RpmHeader::constPtr getHeaderIfPosttrans(const Pathname &rpmPackage_r)
Cache RpmHeader for consecutive hasPosttransScript / collectScriptForPackage calls.
boost::scoped_ptr< filesystem::TmpDir > _ptrTmpdir
Pathname tmpDir()
Lazy create tmpdir on demand.
std::optional< Dumpfile > _dumpfile
bool collectDumpPosttransLines(const std::vector< std::string > &runposttrans_r)
Return whether runposttrans lines were collected.
std::optional< ScriptList > _scripts
void collectPosttransInfo(const Pathname &rpmPackage_r, const std::vector< std::string > &runposttrans_r)
void collectScriptFromHeader(rpm::RpmHeader::constPtr pkg)
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
std::list< std::pair< std::string, std::string > > ScriptList
<posttrans script basename, pkgname> pairs.
bool hasPosttransScript(const Pathname &rpmPackage_r)
void executeScripts(rpm::RpmDb &rpm_r)
Execute the remembered scripts.
std::ostream & dumpOn(std::ostream &str, const RpmPostTransCollector::Impl &obj)
Verbose stream output.
std::pair< Pathname, rpm::RpmHeader::constPtr > _headercache
std::ostream & operator<<(std::ostream &str, const RpmPostTransCollector::Impl &obj)
Stream output.
friend std::ostream & dumpOn(std::ostream &str, const Impl &obj)
void collectScriptForPackage(const Pathname &rpmPackage_r)
Impl(const Pathname &root_r)
Extract and remember posttrans scripts for later execution.
RpmPostTransCollector(const Pathname &root_r)
Default ctor.
void collectPosttransInfo(const Pathname &rpmPackage_r, const std::vector< std::string > &runposttrans_r)
Extract and remember a packages posttrans script or dump_posttrans lines for later execution.
void executeScripts(rpm::RpmDb &rpm_r)
Execute the remembered scripts and/or or dump_posttrans lines.
RW_pointer< Impl > _pimpl
Implementation class.
bool hasPosttransScript(const Pathname &rpmPackage_r)
Test whether a package defines a posttrans script.
~RpmPostTransCollector()
Dtor.
void discardScripts()
Discard all remembered scripts and/or or dump_posttrans lines.
Interface to the rpm program.
int runposttrans(const Pathname &filename_r, std::function< void(const std::string &)> output_r)
Run collected posttrans and transfiletrigger(postun|in) if rpm --runposttrans is supported.
Subclass to retrieve database content.
bool findByName(const std::string &name_r)
Reset to iterate all packages with a certain name.
String related utilities and Regular expression matching.
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
int forEachLine(std::istream &str_r, function< bool(int, std::string)> consume_r)
Simple lineparser: Call functor consume_r for each line.
std::string numstring(char n, int w=0)
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
\relates regex \ingroup ZYPP_STR_REGEX \relates regex \ingroup ZYPP_STR_REGEX
std::ostream & dumpOn(std::ostream &str, const RpmPostTransCollector &obj)
std::ostream & operator<<(std::ostream &str, const CommitPackageCache &obj)
Easy-to use interface to the ZYPP dependency resolver.
JobReport convenience sending this instance of UserData with each message.
bool error(const std::string &msg_r)
bool info(const std::string &msg_r)
bool warning(const std::string &msg_r)
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Data regarding the dumpfile used if rpm --runposttrans is supported.
bool _runposttrans
Set to false if rpm lost –runposttrans support during transaction.
Dumpfile(Pathname dumpfile_r)
Pathname _dumpfile
The file holding the collected dump_posttrans: lines.
size_t _numscripts
Number of scripts we collected (roughly estimated)