X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FVCBackend.cpp;h=bc47719480488acfadb71e80ff61652253c713ed;hb=66d0d61b0c269ef7d5a0d61dc3067d3172a6ac3f;hp=f2057cd360441051e0cf8a94c5ed080ae28dfe26;hpb=85b1bba640f8486d25207c84a541e3f8b4acf917;p=lyx.git diff --git a/src/VCBackend.cpp b/src/VCBackend.cpp index f2057cd360..bc47719480 100644 --- a/src/VCBackend.cpp +++ b/src/VCBackend.cpp @@ -65,6 +65,40 @@ int VCS::doVCCommand(string const & cmd, FileName const & path, bool reportError } +bool VCS::makeRCSRevision(string const &version, string &revis) const +{ + string rev = revis; + + if (isStrInt(rev)) { + int back = convert(rev); + // if positive use as the last number in the whole revision string + if (back > 0) { + string base; + rsplit(version, base , '.' ); + rev = base + "." + rev; + } + if (back == 0) + rev = version; + // we care about the last number from revision string + // in case of backward indexing + if (back < 0) { + string cur, base; + cur = rsplit(version, base , '.' ); + if (!isStrInt(cur)) + return false; + int want = convert(cur) + back; + if (want <= 0) + return false; + + rev = base + "." + convert(want); + } + } + + revis = rev; + return true; +} + + ///////////////////////////////////////////////////////////////////// // // RCS @@ -195,9 +229,30 @@ bool RCS::checkInEnabled() return owner_ && !owner_->isReadonly(); } + bool RCS::isCheckInWithConfirmation() { - //FIXME diff + // FIXME one day common getDiff for all backends + // docstring diff; + // if (getDiff(file, diff) && diff.empty()) + // return false; + + FileName tmpf = FileName::tempName("lyxvcout"); + if (tmpf.empty()) { + LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf); + return true; + } + + doVCCommandCall("rcsdiff " + quoteName(owner_->absFileName()) + + " > " + quoteName(tmpf.toFilesystemEncoding()), + FileName(owner_->filePath())); + + docstring diff = tmpf.fileContents("UTF-8"); + tmpf.erase(); + + if (diff.empty()) + return false; + return true; } @@ -232,6 +287,9 @@ bool RCS::repoUpdateEnabled() string RCS::lockingToggle() { + //FIXME this might be actually possible, study rcs -U, rcs -L. + //State should be easy to get inside scanMaster. + //It would fix #4370 and make rcs/svn usage even more closer. lyxerr << "Sorry, not implemented." << endl; return string(); } @@ -243,13 +301,15 @@ bool RCS::lockingToggleEnabled() } -void RCS::revert() +bool RCS::revert() { - doVCCommand("co -f -u" + version_ + " " + if (doVCCommand("co -f -u" + version_ + " " + quoteName(onlyFileName(owner_->absFileName())), - FileName(owner_->filePath())); + FileName(owner_->filePath()))) + return false; // We ignore changes and just reload! owner_->markClean(); + return true; } @@ -303,31 +363,8 @@ string RCS::revisionInfo(LyXVC::RevisionInfo const info) bool RCS::prepareFileRevision(string const &revis, string & f) { string rev = revis; - - if (isStrInt(rev)) { - int back = convert(rev); - // if positive use as the last number in the whole revision string - if (back > 0) { - string base; - rsplit(version_, base , '.' ); - rev = base + "." + rev; - } - if (back == 0) - rev = version_; - // we care about the last number from revision string - // in case of backward indexing - if (back < 0) { - string cur, base; - cur = rsplit(version_, base , '.' ); - if (!isStrInt(cur)) - return false; - int want = convert(cur) + back; - if (want <= 0) - return false; - - rev = base + "." + convert(want); - } - } + if (!VCS::makeRCSRevision(version_, rev)) + return false; FileName tmpf = FileName::tempName("lyxvcrev_" + rev + "_"); if (tmpf.empty()) { @@ -363,6 +400,7 @@ CVS::CVS(FileName const & m, FileName const & f) { master_ = m; file_ = f; + have_rev_info_ = false; scanMaster(); } @@ -475,6 +513,23 @@ docstring CVS::toString(CvsStatus status) const } +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); +} + + +int CVS::doVCCommandCallWithOutput(std::string const & cmd, + support::FileName const & path, + support::FileName const & output) +{ + string redirection = output.empty() ? "" : " > " + quoteName(output.toFilesystemEncoding()); + return doVCCommandCall(cmd + redirection, path); +} + + CVS::CvsStatus CVS::getStatus() { FileName tmpf = FileName::tempName("lyxvcout"); @@ -483,9 +538,8 @@ CVS::CvsStatus CVS::getStatus() return StatusError; } - if (doVCCommand("cvs status " + getTarget(File) - + " > " + quoteName(tmpf.toFilesystemEncoding()), - FileName(owner_->filePath()))) { + if (doVCCommandCallWithOutput("cvs status " + getTarget(File), + FileName(owner_->filePath()), tmpf)) { tmpf.removeFile(); return StatusError; } @@ -514,6 +568,51 @@ CVS::CvsStatus CVS::getStatus() 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; + } + + int rc = doVCCommandCallWithOutput("cvs log -r" + version_ + + " " + getTarget(File), + FileName(owner_->filePath()), tmpf); + if (rc) { + tmpf.removeFile(); + LYXERR(Debug::LYXVC, "cvs log failed with exit code " << rc); + 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) { @@ -525,9 +624,8 @@ void CVS::registrer(string const & msg) 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); } @@ -549,12 +647,9 @@ int CVS::unedit() 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); } @@ -647,12 +742,14 @@ string CVS::checkOut() 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; @@ -683,8 +780,8 @@ string CVS::repoUpdate() docstring const file = from_utf8(owner_->filePath()); docstring text = bformat(_("There were detected changes " "in the working directory:\n%1$s\n\n" - "In case of file conflict you have to resolve them " - "manually or revert to repository version later."), file); + "Possible file conflicts must be then resolved manually " + "or you will need to revert back to the repository version."), file); int ret = frontend::Alert::prompt(_("Changes detected"), text, 0, 1, _("&Continue"), _("&Abort"), _("View &Log ...")); if (ret == 2 ) { @@ -701,10 +798,23 @@ string CVS::repoUpdate() 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; } @@ -734,7 +844,7 @@ bool CVS::isRevertWithConfirmation() } -void CVS::revert() +bool CVS::revert() { // Reverts to the version in CVS repository and // gets the updated version from the repository. @@ -742,7 +852,7 @@ void CVS::revert() switch (status) { case UpToDate: if (vcstatus != NOLOCKING) - unedit(); + return 0 == unedit(); break; case NeedsMerge: case NeedsCheckout: @@ -759,7 +869,7 @@ void CVS::revert() bformat(_("The document %1$s is not in repository.\n" "You have to check in the first revision before you can revert."), file)) ; - break; + return false; } default: { docstring const file = owner_->fileName().displayName(20); @@ -767,9 +877,10 @@ void CVS::revert() bformat(_("Cannot revert document %1$s to repository version.\n" "The status '%2$s' is unexpected."), file, toString(status))); - break; + return false; } } + return true; } @@ -790,9 +901,9 @@ bool CVS::undoLastEnabled() 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); } @@ -804,21 +915,50 @@ bool CVS::toggleReadOnlyEnabled() 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(); } -bool CVS::prepareFileRevision(string const &, string &) +bool CVS::prepareFileRevision(string const & revis, string & f) { - return false; + string rev = revis; + if (!VCS::makeRCSRevision(version_, rev)) + return false; + + FileName tmpf = FileName::tempName("lyxvcrev_" + rev + "_"); + if (tmpf.empty()) { + LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf); + return false; + } + + doVCCommandWithOutput("cvs update -p -r" + rev + " " + + getTarget(File), + FileName(owner_->filePath()), tmpf); + if (tmpf.isFileEmpty()) + return false; + + f = tmpf.absFileName(); + return true; } bool CVS::prepareFileRevisionEnabled() { - return false; + return true; } @@ -964,7 +1104,24 @@ bool SVN::checkInEnabled() bool SVN::isCheckInWithConfirmation() { - //FIXME diff + // FIXME one day common getDiff and perhaps OpMode for all backends + + FileName tmpf = FileName::tempName("lyxvcout"); + if (tmpf.empty()) { + LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf); + return true; + } + + doVCCommandCall("svn diff " + quoteName(owner_->absFileName()) + + " > " + quoteName(tmpf.toFilesystemEncoding()), + FileName(owner_->filePath())); + + docstring diff = tmpf.fileContents("UTF-8"); + tmpf.erase(); + + if (diff.empty()) + return false; + return true; } @@ -1168,15 +1325,17 @@ bool SVN::lockingToggleEnabled() } -void SVN::revert() +bool SVN::revert() { // Reverts to the version in SVN repository and // gets the updated version from the repository. string const fil = quoteName(onlyFileName(owner_->absFileName())); - doVCCommand("svn revert -q " + fil, - FileName(owner_->filePath())); + if (doVCCommand("svn revert -q " + fil, + FileName(owner_->filePath()))) + return false; owner_->markClean(); + return true; } @@ -1347,7 +1506,7 @@ bool SVN::prepareFileRevision(string const & revis, string & f) FileName tmpf = FileName::tempName("lyxvcrev_" + revname + "_"); if (tmpf.empty()) { LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf); - return N_("Error: Could not generate logfile."); + return false; } doVCCommand("svn cat -r " + revname + " "