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"
34 inline string timestamp()
35 { return zypp::Date::now().form( "%Y-%m-%d %H:%M:%S" ); }
37 inline string userAtHostname()
41 char * tmp = ::cuserid(buf);
45 if (!::gethostname(buf, 255))
46 result += "@" + string(buf);
54 ///////////////////////////////////////////////////////////////////
56 // CLASS NAME : HistoryActionID
58 ///////////////////////////////////////////////////////////////////
60 static std::map<std::string,HistoryActionID::ID> _table;
62 const HistoryActionID HistoryActionID::NONE(HistoryActionID::NONE_e);
63 const HistoryActionID HistoryActionID::INSTALL(HistoryActionID::INSTALL_e);
64 const HistoryActionID HistoryActionID::REMOVE(HistoryActionID::REMOVE_e);
65 const HistoryActionID HistoryActionID::REPO_ADD(HistoryActionID::REPO_ADD_e);
66 const HistoryActionID HistoryActionID::REPO_REMOVE(HistoryActionID::REPO_REMOVE_e);
67 const HistoryActionID HistoryActionID::REPO_CHANGE_ALIAS(HistoryActionID::REPO_CHANGE_ALIAS_e);
68 const HistoryActionID HistoryActionID::REPO_CHANGE_URL(HistoryActionID::REPO_CHANGE_URL_e);
70 HistoryActionID::HistoryActionID(const std::string & strval_r)
71 : _id(parse(strval_r))
74 HistoryActionID::ID HistoryActionID::parse(const std::string & strval_r)
79 _table["install"] = INSTALL_e;
80 _table["remove"] = REMOVE_e;
81 _table["radd"] = REPO_ADD_e;
82 _table["rremove"] = REPO_REMOVE_e;
83 _table["ralias"] = REPO_CHANGE_ALIAS_e;
84 _table["rurl"] = REPO_CHANGE_URL_e;
85 _table["NONE"] = _table["none"] = HistoryActionID::NONE_e;
88 std::map<std::string,HistoryActionID::ID>::const_iterator it =
89 _table.find(strval_r);
91 if (it == _table.end())
92 WAR << "Unknown history action ID '" + strval_r + "'";
98 const std::string & HistoryActionID::asString(bool pad) const
100 static std::map<ID, std::string> _table;
101 if ( _table.empty() )
104 _table[INSTALL_e] = "install";
105 _table[REMOVE_e] = "remove";
106 _table[REPO_ADD_e] = "radd";
107 _table[REPO_REMOVE_e] = "rremove";
108 _table[REPO_CHANGE_ALIAS_e] = "ralias";
109 _table[REPO_CHANGE_URL_e] = "rurl";
110 _table[NONE_e] = "NONE";
112 // add spaces so that the size of the returned string is always 7 (for now)
114 return _table[_id].append(7 - _table[_id].size(), ' ');
118 std::ostream & operator << (std::ostream & str, const HistoryActionID & id)
119 { return str << id.asString(); }
121 ///////////////////////////////////////////////////////////////////
123 ///////////////////////////////////////////////////////////////////
125 // CLASS NAME : HistoryLog
127 ///////////////////////////////////////////////////////////////////
129 Pathname HistoryLog::_fname(ZConfig::instance().historyLogFile());
130 std::ofstream HistoryLog::_log;
131 unsigned HistoryLog::_refcnt = 0;
132 const char HistoryLog::_sep = '|';
134 ///////////////////////////////////////////////////////////////////
136 HistoryLog::HistoryLog( const Pathname & rootdir )
139 if (!rootdir.empty() && rootdir.absolute())
140 _fname = rootdir / ZConfig::instance().historyLogFile();
143 void HistoryLog::openLog()
145 if ( !_fname.empty() )
148 _log.open( _fname.asString().c_str(), std::ios::out|std::ios::app );
150 ERR << "Could not open logfile '" << _fname << "'" << endl;
154 void HistoryLog::closeLog()
160 void HistoryLog::refUp()
167 void HistoryLog::refDown()
175 void HistoryLog::setRoot( const Pathname & rootdir )
177 if (rootdir.empty() || !rootdir.absolute())
183 _fname = rootdir / "/var/log/zypp/history";
184 filesystem::assert_dir( _fname.dirname() );
185 MIL << "installation log file " << _fname << endl;
192 const Pathname & HistoryLog::fname()
195 /////////////////////////////////////////////////////////////////////////
197 void HistoryLog::comment( const string & comment, bool timestamp )
204 _log << ::timestamp() << " ";
206 const char * s = comment.c_str();
208 unsigned size = comment.size();
210 // ignore the last newline
211 if (comment[size-1] == '\n')
214 for ( unsigned i = 0; i < size; ++i, ++c )
217 _log << string( s, c + 1 - s ) << "# ";
222 _log << std::string( s, c-s );
227 /////////////////////////////////////////////////////////////////////////
229 void HistoryLog::install( const PoolItem & pi )
231 const Package::constPtr p = asKind<Package>(pi.resolvable());
236 << timestamp() // 1 timestamp
237 << _sep << HistoryActionID::INSTALL.asString(true) // 2 action
238 << _sep << p->name() // 3 name
239 << _sep << p->edition() // 4 evr
240 << _sep << p->arch(); // 5 arch
242 if (pi.status().isByUser())
243 _log << _sep << userAtHostname(); // 6 reqested by
244 //else if (pi.status().isByApplHigh() || pi.status().isByApplLow())
245 // _log << _sep << "appl";
250 << _sep << p->repoInfo().alias() // 7 repo alias
251 << _sep << p->checksum().checksum(); // 8 checksum
255 //_log << pi << endl;
259 void HistoryLog::remove( const PoolItem & pi )
261 const Package::constPtr p = asKind<Package>(pi.resolvable());
266 << timestamp() // 1 timestamp
267 << _sep << HistoryActionID::REMOVE.asString(true) // 2 action
268 << _sep << p->name() // 3 name
269 << _sep << p->edition() // 4 evr
270 << _sep << p->arch(); // 5 arch
272 if (pi.status().isByUser())
273 _log << _sep << userAtHostname(); // 6 reqested by
274 //else if (pi.status().isByApplHigh() || pi.status().isByApplLow())
275 // _log << _sep << "appl";
279 // we don't have checksum in rpm db
280 // << _sep << p->checksum().checksum(); // x checksum
284 //_log << pi << endl;
287 /////////////////////////////////////////////////////////////////////////
289 void HistoryLog::addRepository(const RepoInfo & repo)
292 << timestamp() // 1 timestamp
293 << _sep << HistoryActionID::REPO_ADD.asString(true) // 2 action
294 << _sep << repo.alias() // 3 alias
295 // what about the rest of the URLs??
296 << _sep << *repo.baseUrlsBegin() // 4 primary URL
301 void HistoryLog::removeRepository(const RepoInfo & repo)
304 << timestamp() // 1 timestamp
305 << _sep << HistoryActionID::REPO_REMOVE.asString(true) // 2 action
306 << _sep << repo.alias() // 3 alias
311 void HistoryLog::modifyRepository(
312 const RepoInfo & oldrepo, const RepoInfo & newrepo)
314 if (oldrepo.alias() != newrepo.alias())
317 << timestamp() // 1 timestamp
318 << _sep << HistoryActionID::REPO_CHANGE_ALIAS.asString(true) // 2 action
319 << _sep << oldrepo.alias() // 3 old alias
320 << _sep << newrepo.alias(); // 4 new alias
323 if (*oldrepo.baseUrlsBegin() != *newrepo.baseUrlsBegin())
326 << timestamp() // 1 timestamp
327 << _sep << HistoryActionID::REPO_CHANGE_URL.asString(true) // 2 action
328 << _sep << oldrepo.alias() // 3 old url
329 << _sep << newrepo.alias(); // 4 new url
333 ///////////////////////////////////////////////////////////////////