1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/HistoryLog.cc
16 #include "zypp/ZConfig.h"
17 #include "zypp/base/String.h"
18 #include "zypp/base/Logger.h"
20 #include "zypp/PathInfo.h"
21 #include "zypp/Date.h"
23 #include "zypp/PoolItem.h"
24 #include "zypp/Package.h"
25 #include "zypp/RepoInfo.h"
27 #include "zypp/HistoryLog.h"
28 #include "zypp/HistoryLogData.h"
35 inline string timestamp()
36 { return zypp::Date::now().form( HISTORY_LOG_DATE_FORMAT ); }
38 inline string userAtHostname()
42 char * tmp = ::cuserid(buf);
46 if (!::gethostname(buf, 255))
47 result += "@" + string(buf);
52 static std::string pidAndAppname()
54 static std::string _val;
57 pid_t mypid = getpid();
58 zypp::Pathname p( "/proc/"+zypp::str::numstring(mypid)+"/exe" );
59 zypp::Pathname myname( zypp::filesystem::readlink( p ) );
61 _val += zypp::str::numstring(mypid);
63 _val += myname.basename();
73 const char _sep = '|';
77 Pathname _fnameLastFail;
82 _fname = ZConfig::instance().historyLogFile();
85 _log.open( _fname.asString().c_str(), std::ios::out|std::ios::app );
86 if( !_log && _fnameLastFail != _fname )
88 ERR << "Could not open logfile '" << _fname << "'" << endl;
89 _fnameLastFail = _fname;
93 inline void closeLog()
106 inline void refDown()
114 ///////////////////////////////////////////////////////////////////
116 // CLASS NAME : HistoryLog
118 ///////////////////////////////////////////////////////////////////
120 HistoryLog::HistoryLog( const Pathname & rootdir )
126 HistoryLog::~HistoryLog()
131 void HistoryLog::setRoot( const Pathname & rootdir )
133 if ( ! rootdir.absolute() )
139 _fname = rootdir / ZConfig::instance().historyLogFile();
140 filesystem::assert_dir( _fname.dirname() );
141 MIL << "installation log file " << _fname << endl;
147 const Pathname & HistoryLog::fname()
149 if ( _fname.empty() )
150 _fname = ZConfig::instance().historyLogFile();
154 /////////////////////////////////////////////////////////////////////////
156 void HistoryLog::comment( const string & comment, bool timestamp )
163 _log << ::timestamp() << " ";
165 const char * s = comment.c_str();
167 unsigned size = comment.size();
169 // ignore the last newline
170 if (comment[size-1] == '\n')
173 for ( unsigned i = 0; i < size; ++i, ++c )
176 _log << string( s, c + 1 - s ) << "# ";
181 _log << std::string( s, c-s );
186 /////////////////////////////////////////////////////////////////////////
188 void HistoryLog::install( const PoolItem & pi )
190 const Package::constPtr p = asKind<Package>(pi.resolvable());
195 << timestamp() // 1 timestamp
196 << _sep << HistoryActionID::INSTALL.asString(true) // 2 action
197 << _sep << p->name() // 3 name
198 << _sep << p->edition() // 4 evr
199 << _sep << p->arch(); // 5 arch
201 // ApplLow is what the solver selected on behalf of the user.
202 if (pi.status().isByUser() || pi.status().isByApplLow() )
203 _log << _sep << userAtHostname(); // 6 reqested by
204 else if (pi.status().isByApplHigh())
205 _log << _sep << pidAndAppname();
210 << _sep << p->repoInfo().alias() // 7 repo alias
211 << _sep << p->checksum().checksum() // 8 checksum
212 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 9 userdata
217 void HistoryLog::remove( const PoolItem & pi )
219 const Package::constPtr p = asKind<Package>(pi.resolvable());
224 << timestamp() // 1 timestamp
225 << _sep << HistoryActionID::REMOVE.asString(true) // 2 action
226 << _sep << p->name() // 3 name
227 << _sep << p->edition() // 4 evr
228 << _sep << p->arch(); // 5 arch
230 // ApplLow is what the solver selected on behalf of the user.
231 if ( pi.status().isByUser() || pi.status().isByApplLow() )
232 _log << _sep << userAtHostname(); // 6 reqested by
233 else if (pi.status().isByApplHigh())
234 _log << _sep << pidAndAppname();
239 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 7 userdata
243 /////////////////////////////////////////////////////////////////////////
245 void HistoryLog::addRepository(const RepoInfo & repo)
248 << timestamp() // 1 timestamp
249 << _sep << HistoryActionID::REPO_ADD.asString(true) // 2 action
250 << _sep << str::escape(repo.alias(), _sep) // 3 alias
251 << _sep << str::escape(repo.url().asString(), _sep) // 4 primary URL
252 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata
257 void HistoryLog::removeRepository(const RepoInfo & repo)
260 << timestamp() // 1 timestamp
261 << _sep << HistoryActionID::REPO_REMOVE.asString(true) // 2 action
262 << _sep << str::escape(repo.alias(), _sep) // 3 alias
263 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 4 userdata
268 void HistoryLog::modifyRepository(
269 const RepoInfo & oldrepo, const RepoInfo & newrepo)
271 if (oldrepo.alias() != newrepo.alias())
274 << timestamp() // 1 timestamp
275 << _sep << HistoryActionID::REPO_CHANGE_ALIAS.asString(true) // 2 action
276 << _sep << str::escape(oldrepo.alias(), _sep) // 3 old alias
277 << _sep << str::escape(newrepo.alias(), _sep) // 4 new alias
278 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata
281 if ( oldrepo.url() != newrepo.url() )
284 << timestamp() // 1 timestamp
285 << _sep << HistoryActionID::REPO_CHANGE_URL.asString(true) // 2 action
286 << _sep << str::escape(oldrepo.url().asString(), _sep) // 3 old url
287 << _sep << str::escape(newrepo.url().asString(), _sep) // 4 new url
288 << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata
293 ///////////////////////////////////////////////////////////////////