libzypp 17.28.8
RpmPostTransCollector.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
11#include <iostream>
12#include <fstream>
13#include <zypp/base/LogTools.h>
14#include <zypp/base/NonCopyable.h>
15#include <zypp/base/Gettext.h>
17
18#include <zypp/TmpPath.h>
19#include <zypp/PathInfo.h>
20#include <zypp/HistoryLog.h>
21#include <zypp/ZYppCallbacks.h>
22#include <zypp/ExternalProgram.h>
25#include <zypp/ZConfig.h>
26#include <zypp/ZYppCallbacks.h>
27
28using std::endl;
29#undef ZYPP_BASE_LOGGER_LOGGROUP
30#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::posttrans"
31
33namespace zypp
34{
36 namespace target
37 {
38
44 {
45 friend std::ostream & operator<<( std::ostream & str, const Impl & obj );
46 friend std::ostream & dumpOn( std::ostream & str, const Impl & obj );
47 public:
48 Impl( const Pathname & root_r )
49 : _root( root_r )
50 {}
51
53 { if ( !_scripts.empty() ) discardScripts(); }
54
57 {
59 if ( ! pkg )
60 {
61 WAR << "Unexpectedly this is no package: " << rpmPackage_r << endl;
62 return false;
63 }
64
65 std::string prog( pkg->tag_posttransprog() );
66 if ( prog.empty() || prog == "<lua>" ) // by now leave lua to rpm
67 return false;
68
69 filesystem::TmpFile script( tmpDir(), rpmPackage_r->basename() );
70 filesystem::addmod( script.path(), 0500 );
71 script.autoCleanup( false ); // no autodelete; within a tmpdir
72 {
73 std::ofstream out( script.path().c_str() );
74 out << "#! " << pkg->tag_posttransprog() << endl
75 << pkg->tag_posttrans() << endl;
76 }
77 _scripts.push_back( std::make_pair( script.path().basename(), pkg->tag_name() ) );
78 MIL << "COLLECT posttrans: '" << PathInfo( script.path() ) << "' for package: '" << pkg->tag_name() << "'" << endl;
79 //DBG << "PROG: " << pkg->tag_posttransprog() << endl;
80 //DBG << "SCRPT: " << pkg->tag_posttrans() << endl;
81 return true;
82 }
83
86 {
87 if ( _scripts.empty() )
88 return true;
89
90 HistoryLog historylog;
91
92 Pathname noRootScriptDir( ZConfig::instance().update_scriptsPath() / tmpDir().basename() );
93
94 ProgressData scriptProgress( static_cast<ProgressData::value_type>(_scripts.size()) );
96 scriptProgress.sendTo( ProgressReportAdaptor( ProgressData::ReceiverFnc(), report ) );
97
98 bool firstScript = true;
99 while ( ! _scripts.empty() )
100 {
101 const auto &scriptPair = _scripts.front();
102 const std::string & script = scriptPair.first;
103 const std::string & pkgident( script.substr( 0, script.size()-6 ) ); // strip tmp file suffix
104
105 scriptProgress.name( str::Format(_("Executing %%posttrans script '%1%'")) % pkgident );
106
107 bool canContinue = true;
108 if (firstScript) {
109 firstScript = false;
110 canContinue = scriptProgress.toMin();
111 } else {
112 canContinue = scriptProgress.incr();
113 }
114
115 if (!canContinue) {
116 str::Str msg;
117 msg << "Execution of %posttrans scripts cancelled";
118 WAR << msg << endl;
119 historylog.comment( msg, true /*timestamp*/);
120 JobReport::warning( msg );
121 return false;
122 }
123
124 int npkgs = 0;
126 for ( it.findByName( scriptPair.second ); *it; ++it )
127 npkgs++;
128
129 MIL << "EXECUTE posttrans: " << script << " with argument: " << npkgs << endl;
131 "/bin/sh",
132 (noRootScriptDir/script).asString(),
133 str::numstring( npkgs )
134 };
135 ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout, false, -1, true, _root );
136
137 str::Str collect;
138 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
139 {
140 DBG << line;
141 collect << " " << line;
142 }
143
144 //script was executed, remove it from the list
145 _scripts.pop_front();
146
147 int ret = prog.close();
148 const std::string & scriptmsg( collect );
149
150 if ( ret != 0 || ! scriptmsg.empty() )
151 {
152 if ( ! scriptmsg.empty() )
153 {
154 str::Str msg;
155 msg << "Output of " << pkgident << " %posttrans script:\n" << scriptmsg;
156 historylog.comment( msg, true /*timestamp*/);
157 JobReport::UserData userData( "cmdout", "%posttrans" );
158 JobReport::info( msg, userData );
159 }
160
161 if ( ret != 0 )
162 {
163 str::Str msg;
164 msg << pkgident << " %posttrans script failed (returned " << ret << ")";
165 WAR << msg << endl;
166 historylog.comment( msg, true /*timestamp*/);
167 JobReport::warning( msg );
168 }
169 }
170 }
171
172 //show a final message
173 scriptProgress.name( _("Executing %posttrans scripts") );
174 scriptProgress.toMax();
175 _scripts.clear();
176 return true;
177 }
178
181 {
182 if ( _scripts.empty() )
183 return;
184
185 HistoryLog historylog;
186
187 str::Str msg;
188 msg << "%posttrans scripts skipped while aborting:\n";
189 for ( const auto & script : _scripts )
190 {
191 const std::string & pkgident( script.first.substr( 0, script.first.size()-6 ) ); // strip tmp file suffix
192 WAR << "UNEXECUTED posttrans: " << script.first << endl;
193 msg << " " << pkgident << "\n";
194 }
195
196 historylog.comment( msg, true /*timestamp*/);
197 JobReport::warning( msg );
198
199 _scripts.clear();
200 }
201
202
203 private:
206 {
207 if ( !_ptrTmpdir ) _ptrTmpdir.reset( new filesystem::TmpDir( _root / ZConfig::instance().update_scriptsPath(), "posttrans" ) );
208 DBG << _ptrTmpdir->path() << endl;
209 return _ptrTmpdir->path();
210 }
211
212 private:
214 std::list< std::pair< std::string, std::string > > _scripts;
215 boost::scoped_ptr<filesystem::TmpDir> _ptrTmpdir;
216 };
217
219 inline std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector::Impl & obj )
220 { return str << "RpmPostTransCollector::Impl"; }
221
223 inline std::ostream & dumpOn( std::ostream & str, const RpmPostTransCollector::Impl & obj )
224 { return str << obj; }
225
227 //
228 // CLASS NAME : RpmPostTransCollector
229 //
231
233 : _pimpl( new Impl( root_r ) )
234 {}
235
237 {}
238
240 { return _pimpl->collectScriptFromPackage( rpmPackage_r ); }
241
243 { return _pimpl->executeScripts(); }
244
246 { return _pimpl->discardScripts(); }
247
248 std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector & obj )
249 { return str << *obj._pimpl; }
250
251 std::ostream & dumpOn( std::ostream & str, const RpmPostTransCollector & obj )
252 { return dumpOn( str, *obj._pimpl ); }
253
254 } // namespace target
256} // namespace zypp
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:94
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.
Definition: HistoryLog.h:57
void comment(const std::string &comment, bool timestamp=false)
Log a comment (even multiline).
Definition: HistoryLog.cc:188
Maintain [min,max] and counter (value) for progress counting.
Definition: ProgressData.h:131
long long value_type
Definition: ProgressData.h:133
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
Definition: ProgressData.h:226
bool toMax()
Set counter value to current max value (unless no range).
Definition: ProgressData.h:273
void name(const std::string &name_r)
Set counter name.
Definition: ProgressData.h:222
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: ProgressData.h:139
bool incr(value_type val_r=1)
Increment counter value (default by 1).
Definition: ProgressData.h:261
bool toMin()
Set counter value to current min value.
Definition: ProgressData.h:269
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:126
Typesafe passing of user data via callbacks.
Definition: UserData.h:39
std::string receiveLine()
Read one line from the input stream.
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
const char * c_str() const
String representation.
Definition: Pathname.h:110
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition: TmpPath.h:178
Provide a new empty temporary file and delete it when no longer needed.
Definition: TmpPath.h:128
Pathname path() const
Definition: TmpPath.cc:146
bool autoCleanup() const
Whether path is valid and deleted when the last reference drops.
Definition: TmpPath.cc:163
RpmPostTransCollector implementation.
bool executeScripts()
Execute the remembered scripts.
void discardScripts()
Discard all remembered scrips.
boost::scoped_ptr< filesystem::TmpDir > _ptrTmpdir
Pathname tmpDir()
Lazy create tmpdir on demand.
std::list< std::pair< std::string, std::string > > _scripts
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
bool collectScriptFromPackage(ManagedFile rpmPackage_r)
Extract and remember a packages posttrans script for later execution.
std::ostream & dumpOn(std::ostream &str, const RpmPostTransCollector::Impl &obj)
Verbose stream output.
std::ostream & operator<<(std::ostream &str, const RpmPostTransCollector::Impl &obj)
Stream output.
friend std::ostream & dumpOn(std::ostream &str, const Impl &obj)
Extract and remember posttrans scripts for later execution.
RpmPostTransCollector(const Pathname &root_r)
Default ctor.
RW_pointer< Impl > _pimpl
Implementation class.
bool collectScriptFromPackage(ManagedFile rpmPackage_r)
Extract and remember a packages posttrans script for later execution.
bool executeScripts()
Execute the remembered scripts.
void discardScripts()
Discard all remembered scrips.
static RpmHeader::constPtr readPackage(const Pathname &path, VERIFICATION verification=VERIFY)
Get an accessible packages data from disk.
Definition: RpmHeader.cc:210
intrusive_ptr< const RpmHeader > constPtr
Definition: RpmHeader.h:65
Subclass to retrieve database content.
Definition: librpmDb.h:336
bool findByName(const std::string &name_r)
Reset to iterate all packages with a certain name.
Definition: librpmDb.cc:776
String related utilities and Regular expression matching.
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition: NonCopyable.h:26
int addmod(const Pathname &path, mode_t mode)
Add the mode bits to the file given by path.
Definition: PathInfo.cc:1101
std::string numstring(char n, int w=0)
Definition: String.h:289
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.
Definition: CodePitfalls.doc:2
std::string asString(const TriBool &val_r, const std::string &istr_r=std::string(), const std::string &tstr_r=std::string(), const std::string &fstr_r=std::string())
Definition: TriBool.h:44
static bool warning(const std::string &msg_r, const UserData &userData_r=UserData())
send warning text
static bool info(const std::string &msg_r, const UserData &userData_r=UserData())
send message text
Convenient building of std::string with boost::format.
Definition: String.h:253
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:212
#define _(MSG)
Definition: Gettext.h:37
#define DBG
Definition: Logger.h:95
#define MIL
Definition: Logger.h:96
#define WAR
Definition: Logger.h:97