1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/RpmPostTransCollector.cc
13 #include "zypp/base/LogTools.h"
14 #include "zypp/base/NonCopyable.h"
15 #include "zypp/target/RpmPostTransCollector.h"
17 #include "zypp/TmpPath.h"
18 #include "zypp/PathInfo.h"
19 #include "zypp/HistoryLog.h"
20 #include "zypp/ZYppCallbacks.h"
21 #include "zypp/ExternalProgram.h"
22 #include "zypp/target/rpm/RpmHeader.h"
23 #include "zypp/ZConfig.h"
26 #undef ZYPP_BASE_LOGGER_LOGGROUP
27 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::posttrans"
29 ///////////////////////////////////////////////////////////////////
32 ///////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////
37 /// \class RpmPostTransCollector::Impl
38 /// \brief RpmPostTransCollector implementation.
39 ///////////////////////////////////////////////////////////////////
40 class RpmPostTransCollector::Impl : private base::NonCopyable
42 friend std::ostream & operator<<( std::ostream & str, const Impl & obj );
43 friend std::ostream & dumpOn( std::ostream & str, const Impl & obj );
45 Impl( const Pathname & root_r )
50 { if ( !_scripts.empty() ) discardScripts(); }
52 /** Extract and remember a packages %posttrans script for later execution. */
53 bool collectScriptFromPackage( ManagedFile rpmPackage_r )
55 rpm::RpmHeader::constPtr pkg( rpm::RpmHeader::readPackage( rpmPackage_r, rpm::RpmHeader::NOVERIFY ) );
57 std::string prog( pkg->tag_posttransprog() );
58 if ( prog.empty() || prog == "<lua>" ) // by now leave lua to rpm
61 filesystem::TmpFile script( tmpDir(), rpmPackage_r->basename() );
62 filesystem::addmod( script.path(), 0500 );
63 script.autoCleanup( false ); // no autodelete; within a tmpdir
65 std::ofstream out( script.path().c_str() );
66 out << "#! " << pkg->tag_posttransprog() << endl
67 << pkg->tag_posttrans() << endl;
69 _scripts.push_back( script.path().basename() );
70 MIL << "COLLECT posttrans: " << PathInfo( script.path() ) << endl;
71 //DBG << "PROG: " << pkg->tag_posttransprog() << endl;
72 //DBG << "SCRPT: " << pkg->tag_posttrans() << endl;
76 /** Execute te remembered scripts. */
79 if ( _scripts.empty() )
82 HistoryLog historylog;
84 Pathname noRootScriptDir( ZConfig::instance().update_scriptsPath() / tmpDir().basename() );
86 for ( auto && script : _scripts )
88 MIL << "EXECUTE posttrans: " << script << endl;
89 ExternalProgram prog( (noRootScriptDir/script).asString(), ExternalProgram::Stderr_To_Stdout, false, -1, true, _root );
92 for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
95 collect << " " << line;
97 int ret = prog.close();
98 const std::string & scriptmsg( collect );
100 if ( ret != 0 || ! scriptmsg.empty() )
102 const std::string & pkgident( script.substr( 0, script.size()-6 ) ); // strip tmp file suffix
104 if ( ! scriptmsg.empty() )
107 msg << "Output of " << pkgident << " %posttrans script:\n" << scriptmsg;
108 historylog.comment( msg, true /*timestamp*/);
109 JobReport::info( msg );
115 msg << pkgident << " %posttrans script failed (returned " << ret << ")";
117 historylog.comment( msg, true /*timestamp*/);
118 JobReport::warning( msg );
125 /** Discard all remembered scrips. */
126 void discardScripts()
128 if ( _scripts.empty() )
131 HistoryLog historylog;
134 msg << "%posttrans scripts skipped while aborting:\n";
135 for ( auto && script : _scripts )
137 const std::string & pkgident( script.substr( 0, script.size()-6 ) ); // strip tmp file suffix
138 WAR << "UNEXECUTED posttrans: " << script << endl;
139 msg << " " << pkgident << "\n";
142 historylog.comment( msg, true /*timestamp*/);
143 JobReport::warning( msg );
149 /** Lazy create tmpdir on demand. */
152 if ( !_ptrTmpdir ) _ptrTmpdir.reset( new filesystem::TmpDir( _root / ZConfig::instance().update_scriptsPath(), "posttrans" ) );
153 DBG << _ptrTmpdir->path() << endl;
154 return _ptrTmpdir->path();
159 std::list<std::string> _scripts;
160 boost::scoped_ptr<filesystem::TmpDir> _ptrTmpdir;
163 /** \relates RpmPostTransCollector::Impl Stream output */
164 inline std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector::Impl & obj )
165 { return str << "RpmPostTransCollector::Impl"; }
167 /** \relates RpmPostTransCollector::Impl Verbose stream output */
168 inline std::ostream & dumpOn( std::ostream & str, const RpmPostTransCollector::Impl & obj )
169 { return str << obj; }
171 ///////////////////////////////////////////////////////////////////
173 // CLASS NAME : RpmPostTransCollector
175 ///////////////////////////////////////////////////////////////////
177 RpmPostTransCollector::RpmPostTransCollector( const Pathname & root_r )
178 : _pimpl( new Impl( root_r ) )
181 RpmPostTransCollector::~RpmPostTransCollector()
184 bool RpmPostTransCollector::collectScriptFromPackage( ManagedFile rpmPackage_r )
185 { return _pimpl->collectScriptFromPackage( rpmPackage_r ); }
187 void RpmPostTransCollector::executeScripts()
188 { return _pimpl->executeScripts(); }
190 void RpmPostTransCollector::discardScripts()
191 { return _pimpl->discardScripts(); }
193 std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector & obj )
194 { return str << *obj._pimpl; }
196 std::ostream & dumpOn( std::ostream & str, const RpmPostTransCollector & obj )
197 { return dumpOn( str, *obj._pimpl ); }
199 } // namespace target
200 ///////////////////////////////////////////////////////////////////
202 ///////////////////////////////////////////////////////////////////