libzypp  17.25.6
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 
28 using std::endl;
29 #undef ZYPP_BASE_LOGGER_LOGGROUP
30 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::posttrans"
31 
33 namespace 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()) );
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;
130  ExternalProgram prog( (noRootScriptDir/script).asString() + " " +str::numstring( npkgs ), ExternalProgram::Stderr_To_Stdout, false, -1, true, _root );
131 
132  str::Str collect;
133  for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
134  {
135  DBG << line;
136  collect << " " << line;
137  }
138 
139  //script was executed, remove it from the list
140  _scripts.pop_front();
141 
142  int ret = prog.close();
143  const std::string & scriptmsg( collect );
144 
145  if ( ret != 0 || ! scriptmsg.empty() )
146  {
147  if ( ! scriptmsg.empty() )
148  {
149  str::Str msg;
150  msg << "Output of " << pkgident << " %posttrans script:\n" << scriptmsg;
151  historylog.comment( msg, true /*timestamp*/);
152  JobReport::UserData userData( "cmdout", "%posttrans" );
153  JobReport::info( msg, userData );
154  }
155 
156  if ( ret != 0 )
157  {
158  str::Str msg;
159  msg << pkgident << " %posttrans script failed (returned " << ret << ")";
160  WAR << msg << endl;
161  historylog.comment( msg, true /*timestamp*/);
162  JobReport::warning( msg );
163  }
164  }
165  }
166 
167  //show a final message
168  scriptProgress.name( _("Executing %posttrans scripts") );
169  scriptProgress.toMax();
170  _scripts.clear();
171  return true;
172  }
173 
176  {
177  if ( _scripts.empty() )
178  return;
179 
180  HistoryLog historylog;
181 
182  str::Str msg;
183  msg << "%posttrans scripts skipped while aborting:\n";
184  for ( const auto & script : _scripts )
185  {
186  const std::string & pkgident( script.first.substr( 0, script.first.size()-6 ) ); // strip tmp file suffix
187  WAR << "UNEXECUTED posttrans: " << script.first << endl;
188  msg << " " << pkgident << "\n";
189  }
190 
191  historylog.comment( msg, true /*timestamp*/);
192  JobReport::warning( msg );
193 
194  _scripts.clear();
195  }
196 
197 
198  private:
201  {
202  if ( !_ptrTmpdir ) _ptrTmpdir.reset( new filesystem::TmpDir( _root / ZConfig::instance().update_scriptsPath(), "posttrans" ) );
203  DBG << _ptrTmpdir->path() << endl;
204  return _ptrTmpdir->path();
205  }
206 
207  private:
209  std::list< std::pair< std::string, std::string > > _scripts;
210  boost::scoped_ptr<filesystem::TmpDir> _ptrTmpdir;
211  };
212 
214  inline std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector::Impl & obj )
215  { return str << "RpmPostTransCollector::Impl"; }
216 
218  inline std::ostream & dumpOn( std::ostream & str, const RpmPostTransCollector::Impl & obj )
219  { return str << obj; }
220 
222  //
223  // CLASS NAME : RpmPostTransCollector
224  //
226 
228  : _pimpl( new Impl( root_r ) )
229  {}
230 
232  {}
233 
235  { return _pimpl->collectScriptFromPackage( rpmPackage_r ); }
236 
238  { return _pimpl->executeScripts(); }
239 
241  { return _pimpl->discardScripts(); }
242 
243  std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector & obj )
244  { return str << *obj._pimpl; }
245 
246  std::ostream & dumpOn( std::ostream & str, const RpmPostTransCollector & obj )
247  { return dumpOn( str, *obj._pimpl ); }
248 
249  } // namespace target
251 } // namespace zypp
Interface to gettext.
#define _(MSG)
Definition: Gettext.h:37
#define DBG
Definition: Logger.h:78
#define MIL
Definition: Logger.h:79
#define WAR
Definition: Logger.h:80
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:70
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:93
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
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
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
const char * c_str() const
String representation.
Definition: Pathname.h:110
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 & dumpOn(std::ostream &str, const Impl &obj)
bool collectScriptFromPackage(ManagedFile rpmPackage_r)
Extract and remember a packages posttrans script for later execution.
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
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.
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:208
intrusive_ptr< const RpmHeader > constPtr
Definition: RpmHeader.h:64
Subclass to retrieve database content.
Definition: librpmDb.h:337
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:1063
std::string numstring(char n, int w=0)
Definition: String.h:286
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 DefaultIntegral< Tp, TInitial > &obj)
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:250
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:209