Am 04.11.2010 um 16:52 schrieb Stephan Witt: > Am 04.11.2010 um 16:15 schrieb Pavel Sanda: > >> Stephan Witt wrote: >>>>> I'll use an explicit getRevisionInfo() success state flag and return >>>>> string() instead. Ok? >>>> >>>> not sure what exactly do you mean :) >>> >>> That's how I understood your comment, but the new patch is not ready... >>> >>> Like that: >>> >> >> i'm basically happy that the duplicated strings disappeared. >> lyxerr looks more approriate inside getRevisionInfo. > > Ok.
Now I've finished the patch and have a fundamental problem: When a document contains vcs buffer-info insets like vcs-author the reload crashes. The culprit is the owner_->setBusy(false); in VCS::doVCCommand(). The cursor cannot be changed when the buffer load is in progress - it seems. I solved it with using the reportError flag to suppress the cursor changes. I'm sure - it's not the correct solution. But I cannot solve this in a better way. Please help. I'm frustrated. One possible change is to move the info inset variable initialization into file_found_hook()... but this is a static method - again more to change then planned. Anyway, the patch is attached (with the reportError/cursor logic). I'd appreciate any comment. (I fear SVN is affected by that too!) Stephan
Index: src/VCBackend.h =================================================================== --- src/VCBackend.h (Revision 36088) +++ 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,15 @@ 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. + void getRevisionInfo(); + bool have_rev_info_; }; Index: src/VCBackend.cpp =================================================================== --- src/VCBackend.cpp (Revision 36088) +++ src/VCBackend.cpp (Arbeitskopie) @@ -49,18 +49,19 @@ int VCS::doVCCommand(string const & cmd, FileName const & path, bool reportError) { - if (owner_) + if (owner_ && reportError) owner_->setBusy(true); int const ret = doVCCommandCall(cmd, path); - if (owner_) + if (owner_ && reportError) 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; } @@ -366,6 +367,7 @@ { master_ = m; file_ = f; + have_rev_info_ = false; scanMaster(); } @@ -478,6 +480,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 +496,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 +526,51 @@ return status; } +void CVS::getRevisionInfo() +{ + if (have_rev_info_) + return; + have_rev_info_ = true; + FileName tmpf = FileName::tempName("lyxvcout"); + if (tmpf.empty()) { + LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf); + return; + } + + if (doVCCommandWithOutput("cvs log -r" + version_ + + " " + getTarget(File), + FileName(owner_->filePath()), tmpf, false)) { + tmpf.removeFile(); + LYXERR(Debug::LYXVC, "cvs log failed"); + return; + } + + ifstream ifs(tmpf.toFilesystemEncoding().c_str()); + static regex const reg("date: (.*) (.*) (.*); author: (.*); state: (.*);(.*)"); + 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]; + break; + } + } + tmpf.removeFile(); + if (rev_author_cache_.empty()) + LYXERR(Debug::LYXVC, + "Could not retrieve revision info for " << version_ << + " of " << getTarget(File)); +} + + void CVS::registrer(string const & msg) { doVCCommand("cvs -q add -m \"" + msg + "\" " @@ -528,9 +581,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 +604,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 +699,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 +755,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 +857,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 +871,20 @@ string CVS::revisionInfo(LyXVC::RevisionInfo const info) { - if (info == LyXVC::File) - return version_; + if (!version_.empty()) { + getRevisionInfo(); + 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(); }