Am 02.11.2010 um 22:43 schrieb Stephan Witt: > Am 02.11.2010 um 19:27 schrieb Pavel Sanda: > >>> CVS improvement if info inset output is possible (after review) for >>> 2.0-beta? >> >> if its possible to make it simple and stupid using the current philosophy >> then yes. >> if you need to redesign things around, please let it sleep, its too late. > > No worry, basically I want to adapt the SVN idea. > Using the cvs log -r "VCS::version_" command I'd like to parse the log line > and > save the result into - obviously code duplication again - some state variables > inside CVS class.
Here another patch including: * CVS helper method to ease system calls with output redirection (really trivial ;-)) * changes to use that helper method * CVS revision information retrieval in local cache variables * Scan log file after CVS::repoUpdate() and warn the user when conflicts found * extended CVS::revisionInfo() implementation Ok to commit? Stephan
Index: src/VCBackend.h =================================================================== --- src/VCBackend.h (Revision 36011) +++ src/VCBackend.h (Arbeitskopie) @@ -261,6 +261,21 @@ // revision number from scanMaster std::string version_; + /** + * doVCCommandWithOutput + * - call out to the version control utility + * - it is able to collect output in a file + * @param cmd the command to execute + * @param path the path from which to execute + * @param output the path where to store output + * @param reportError display of low level error message dialog + * @return exit status + */ + int doVCCommandWithOutput(std::string const & cmd, + support::FileName const & path, + support::FileName const & output, + bool reportError = true); + /// return the quoted pathname if Directory or filename if File virtual std::string const getTarget(OperationMode opmode) const; /// collect the diff of file or directory against repository @@ -280,6 +295,14 @@ virtual CvsStatus getStatus(); /// convert enum to string virtual docstring toString(CvsStatus status) const; + + /// cache the info values of current file revision + /// author, date and time of commit + std::string rev_author_cache_; + std::string rev_date_cache_; + std::string rev_time_cache_; + /// fills the cache values, returns true if successfull. + bool getRevisionInfo(); }; Index: src/VCBackend.cpp =================================================================== --- src/VCBackend.cpp (Revision 36011) +++ src/VCBackend.cpp (Arbeitskopie) @@ -56,11 +56,12 @@ if (owner_) owner_->setBusy(false); - if (ret && reportError) + if (ret && reportError) { frontend::Alert::error(_("Revision control error."), bformat(_("Some problem occured while running the command:\n" - "'%1$s'."), - from_utf8(cmd))); + "'%1$s'.\n"), + from_utf8(cmd))); + } return ret; } @@ -478,6 +479,14 @@ } +int CVS::doVCCommandWithOutput(string const & cmd, FileName const & path, + FileName const & output, bool reportError) +{ + string redirection = output.empty() ? "" : " > " + quoteName(output.toFilesystemEncoding()); + return doVCCommand(cmd + redirection, path, reportError); +} + + CVS::CvsStatus CVS::getStatus() { FileName tmpf = FileName::tempName("lyxvcout"); @@ -486,9 +495,8 @@ return StatusError; } - if (doVCCommand("cvs status " + getTarget(File) - + " > " + quoteName(tmpf.toFilesystemEncoding()), - FileName(owner_->filePath()))) { + if (doVCCommandWithOutput("cvs status " + getTarget(File), + FileName(owner_->filePath()), tmpf)) { tmpf.removeFile(); return StatusError; } @@ -517,7 +525,44 @@ return status; } +bool CVS::getRevisionInfo() +{ + FileName tmpf = FileName::tempName("lyxvcout"); + if (tmpf.empty()) { + LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf); + return false; + } + + if (doVCCommandWithOutput("cvs log -r" + version_ + " " + getTarget(File), + FileName(owner_->filePath()), tmpf)) { + tmpf.removeFile(); + return false; + } + + ifstream ifs(tmpf.toFilesystemEncoding().c_str()); + static regex const reg("date: (.*) (.*) (.*); author: (.*); state: (.*);(.*)"); + bool result = false; + while (ifs) { + string line; + getline(ifs, line); + LYXERR(Debug::LYXVC, line << "\n"); + if (prefixIs(line, "date:")) { + smatch sm; + regex_match(line, sm, reg); + //sm[0]; // whole matched string + rev_date_cache_ = sm[1]; + rev_time_cache_ = sm[2]; + //sm[3]; // GMT offset + rev_author_cache_ = sm[4]; + result = true; + } + } + tmpf.removeFile(); + return result; +} + + void CVS::registrer(string const & msg) { doVCCommand("cvs -q add -m \"" + msg + "\" " @@ -528,9 +573,8 @@ void CVS::getDiff(OperationMode opmode, FileName const & tmpf) { - doVCCommand("cvs diff " + getTarget(opmode) - + " > " + quoteName(tmpf.toFilesystemEncoding()), - FileName(owner_->filePath()), false); + doVCCommandWithOutput("cvs diff " + getTarget(opmode), + FileName(owner_->filePath()), tmpf, false); } @@ -552,12 +596,9 @@ int CVS::update(OperationMode opmode, FileName const & tmpf) { - string const redirection = tmpf.empty() ? "" - : " > " + quoteName(tmpf.toFilesystemEncoding()); - - return doVCCommand("cvs -q update " - + getTarget(opmode) + redirection, - FileName(owner_->filePath())); + return doVCCommandWithOutput("cvs -q update " + + getTarget(opmode), + FileName(owner_->filePath()), tmpf, false); } @@ -650,12 +691,14 @@ int rc = update(File, tmpf); string log; string const res = scanLogFile(tmpf, log); - if (!res.empty()) + if (!res.empty()) { frontend::Alert::error(_("Revision control error."), bformat(_("Error when updating from repository.\n" "You have to manually resolve the conflicts NOW!\n'%1$s'.\n\n" "After pressing OK, LyX will try to reopen the resolved document."), from_local8bit(res))); + rc = 0; + } tmpf.erase(); return rc ? string() : log.empty() ? "CVS: Proceeded" : "CVS: " + log; @@ -704,10 +747,23 @@ int rc = update(Directory, tmpf); res += "Update log:\n" + tmpf.fileContents("UTF-8"); + LYXERR(Debug::LYXVC, res); + + string log; + string sres = scanLogFile(tmpf, log); + if (!sres.empty()) { + docstring const file = owner_->fileName().displayName(20); + frontend::Alert::error(_("Revision control error."), + bformat(_("Error when updating document %1$s from repository.\n" + "You have to manually resolve the conflicts NOW!\n'%2$s'.\n\n" + "After pressing OK, LyX will try to reopen the resolved document."), + file, from_local8bit(sres))); + rc = 0; + } + tmpf.removeFile(); - LYXERR(Debug::LYXVC, res); - return rc ? string() : "CVS: Proceeded" ; + return rc ? string() : log.empty() ? "CVS: Proceeded" : "CVS: " + log; } @@ -793,9 +849,9 @@ void CVS::getLog(FileName const & tmpf) { - doVCCommand("cvs log " + getTarget(File) - + " > " + quoteName(tmpf.toFilesystemEncoding()), - FileName(owner_->filePath())); + doVCCommandWithOutput("cvs log " + getTarget(File), + FileName(owner_->filePath()), + tmpf); } @@ -807,8 +863,26 @@ string CVS::revisionInfo(LyXVC::RevisionInfo const info) { - if (info == LyXVC::File) - return version_; + if (!version_.empty()) { + if (rev_author_cache_.empty()) { + if (!getRevisionInfo()) { + rev_author_cache_ = to_local8bit(_("unknown author")); + rev_date_cache_ = to_local8bit(_("unknown date")); + rev_time_cache_ = to_local8bit(_("unknown time")); + } + } + switch (info) { + case LyXVC::File: + return version_; + case LyXVC::Author: + return rev_author_cache_; + case LyXVC::Date: + return rev_date_cache_; + case LyXVC::Time: + return rev_time_cache_; + default: ; + } + } return string(); }