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" 49 friend std::ostream &
dumpOn( std::ostream &
str,
const Impl & obj );
52 using ScriptList = std::list< std::pair<std::string,std::string> >;
93 script.autoCleanup(
false );
95 std::ofstream out( script.path().c_str() );
96 out <<
"#! " << pkg->tag_posttransprog() << endl
97 << pkg->tag_posttrans() << endl;
100 _scripts->push_back( std::make_pair( script.path().basename(), pkg->tag_name() ) );
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" };
240 const auto &scriptPair =
_scripts->front();
241 const std::string & script = scriptPair.first;
242 const std::string & pkgident( script.substr( 0, script.size()-6 ) );
243 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 ) )
std::string asString(const Patch::Category &obj)
Interface to the rpm program.
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Data regarding the dumpfile used if rpm --runposttrans is supported.
size_t _numscripts
Number of scripts we collected (roughly estimated)
JobReport convenience sending this instance of UserData with each message.
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
static ZConfig & instance()
Singleton ctor.
bool warning(const std::string &msg_r)
void discardScripts()
Discard all remembered scripts and/or or dump_posttrans lines.
friend std::ostream & dumpOn(std::ostream &str, const Impl &obj)
String related utilities and Regular expression matching.
std::list< std::pair< std::string, std::string > > ScriptList
<posttrans script basename, pkgname> pairs.
bool toMax()
Set counter value to current max value (unless no range).
Impl(const Pathname &root_r)
std::string receiveLine()
Read one line from the input stream.
std::ostream & dumpOn(std::ostream &str, const RpmPostTransCollector::Impl &obj)
Provide a new empty temporary file and delete it when no longer needed.
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
void erase(const std::string &key_r)
Remove key from data.
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.
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...
RW_pointer< Impl > _pimpl
Implementation class.
void collectScriptForPackage(const Pathname &rpmPackage_r)
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
std::vector< std::string > Arguments
RpmPostTransCollector(const Pathname &root_r)
Default ctor.
Extract and remember posttrans scripts for later execution.
Subclass to retrieve database content.
bool hasPosttransScript(const Pathname &rpmPackage_r)
Test whether a package defines a posttrans script.
bool info(const std::string &msg_r)
Pathname tmpDir()
Lazy create tmpdir on demand.
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
bool toMin()
Set counter value to current min value.
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
void executeScripts(rpm::RpmDb &rpm_r)
Execute the remembered scripts.
std::pair< Pathname, rpm::RpmHeader::constPtr > _headercache
Provide a new empty temporary directory and recursively delete it when no longer needed.
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
bool set(const std::string &key_r, AnyType val_r)
Set the value for key (nonconst version always returns true).
bool findByName(const std::string &name_r)
Reset to iterate all packages with a certain name.
int forEachLine(std::istream &str_r, function< bool(int, std::string)> consume_r)
Simple lineparser: Call functor consume_r for each line.
std::optional< Dumpfile > _dumpfile
rpm::RpmHeader::constPtr getHeaderIfPosttrans(const Pathname &rpmPackage_r)
Cache RpmHeader for consecutive hasPosttransScript / collectScriptForPackage calls.
RpmPostTransCollector implementation.
Maintain [min,max] and counter (value) for progress counting.
std::ostream & operator<<(std::ostream &str, const CommitPackageCache &obj)
boost::scoped_ptr< filesystem::TmpDir > _ptrTmpdir
void collectPosttransInfo(const Pathname &rpmPackage_r, const std::vector< std::string > &runposttrans_r)
Writing the zypp history fileReference counted signleton for writhing the zypp history file...
void executeScripts(rpm::RpmDb &rpm_r)
Execute the remembered scripts and/or or dump_posttrans lines.
bool incr(value_type val_r=1)
Increment counter value (default by 1).
void collectScriptFromHeader(rpm::RpmHeader::constPtr pkg)
std::string numstring(char n, int w=0)
std::optional< ScriptList > _scripts
std::ostream & dumpOn(std::ostream &str, const RpmPostTransCollector &obj)
int close()
Wait for the progamm to complete.
Regular expression match result.
bool error(const std::string &msg_r)
bool hasPosttransScript(const Pathname &rpmPackage_r)
Dumpfile(Pathname dumpfile_r)
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.
void discardScripts()
Discard all remembered scrips.
~RpmPostTransCollector()
Dtor.
bool _runposttrans
Set to false if rpm lost –runposttrans support during transaction.
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Wrapper class for ::stat/::lstat.
bool regex_match(const std::string &s, smatch &matches, const regex ®ex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
bool headerHasPosttrans(rpm::RpmHeader::constPtr pkg_r) const
Return whether RpmHeader has a posttrans.
void name(const std::string &name_r)
Set counter name.
bool collectDumpPosttransLines(const std::vector< std::string > &runposttrans_r)
Return whether runposttrans lines were collected.
Pathname _dumpfile
The file holding the collected dump_posttrans: lines.
Easy-to use interface to the ZYPP dependency resolver.
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
UserDataJobReport _myJobReport
JobReport with ContentType "cmdout/%posttrans".
std::ostream & operator<<(std::ostream &str, const RpmPostTransCollector::Impl &obj)
void collectPosttransInfo(const std::vector< std::string > &runposttrans_r)