X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLyXVC.cpp;h=cb2c5488f210b66fe3c7ce0cf71d3bc88c13efdb;hb=c7d29be153debac82e3d2e8865fcc849f0a5f40d;hp=fca70971f5226fc545f40f835d7a86d26217f686;hpb=fbb3abfeac7b65f823b67e41ab5d6bc0a62f3eef;p=lyx.git diff --git a/src/LyXVC.cpp b/src/LyXVC.cpp index fca70971f5..cb2c5488f2 100644 --- a/src/LyXVC.cpp +++ b/src/LyXVC.cpp @@ -3,11 +3,11 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * \author Jean-Marc Lasgouttes * \author Angus Leeming * \author John Levon - * \author André Pönitz + * \author André Pönitz * \author Allan Rae * * Full author contact details are available in file CREDITS. @@ -17,28 +17,21 @@ #include "LyXVC.h" #include "VCBackend.h" -#include "debug.h" #include "Buffer.h" -#include "gettext.h" #include "frontends/alert.h" +#include "support/debug.h" #include "support/filetools.h" -#include "support/lyxlib.h" +#include "support/gettext.h" +#include "support/lstrings.h" +#include "support/TempFile.h" +using namespace std; +using namespace lyx::support; namespace lyx { -using support::bformat; -using support::FileName; -using support::makeAbsPath; -using support::makeDisplayPath; -using support::tempName; - -using std::endl; -using std::string; -using std::pair; - namespace Alert = frontend::Alert; @@ -48,38 +41,94 @@ LyXVC::LyXVC() } -// for the sake of boost::scoped_ptr -LyXVC::~LyXVC() -{} +docstring LyXVC::vcstatus() const +{ + if (!vcs) + return docstring(); + if (locking()) + return bformat(_("%1$s lock"), from_ascii(vcs->vcname())); + else + return from_ascii(vcs->vcname()); +} + + +bool LyXVC::fileInVC(FileName const & fn) +{ + if (!RCS::findFile(fn).empty()) + return true; + if (!CVS::findFile(fn).empty()) + return true; + if (!SVN::findFile(fn).empty()) + return true; + if (!GIT::findFile(fn).empty()) + return true; + return false; +} bool LyXVC::file_found_hook(FileName const & fn) { FileName found_file; // Check if file is under RCS - if (!(found_file = RCS::find_file(fn)).empty()) { - vcs.reset(new RCS(found_file)); - vcs->owner(owner_); + if (!(found_file = RCS::findFile(fn)).empty()) { + vcs.reset(new RCS(found_file, owner_)); return true; } // Check if file is under CVS - if (!(found_file = CVS::find_file(fn)).empty()) { - vcs.reset(new CVS(found_file, fn)); - vcs->owner(owner_); + if (!(found_file = CVS::findFile(fn)).empty()) { + vcs.reset(new CVS(found_file, owner_)); + return true; + } + // Check if file is under SVN + if (!(found_file = SVN::findFile(fn)).empty()) { + vcs.reset(new SVN(found_file, owner_)); + return true; + } + // Check if file is under GIT + if (!(found_file = GIT::findFile(fn)).empty()) { + vcs.reset(new GIT(found_file, owner_)); return true; } + // file is not under any VCS. + vcs.reset(0); return false; } bool LyXVC::file_not_found_hook(FileName const & fn) { - // Check if file is under RCS - if (!RCS::find_file(fn).empty()) - return true; - if (!CVS::find_file(fn).empty()) - return true; + // Check if file is under RCS. + // This happens if we are trying to load non existent + // file on disk, but existent in ,v version. + bool foundRCS = !RCS::findFile(fn).empty(); + bool foundCVS = foundRCS ? false : !CVS::findFile(fn).empty(); + bool foundSVN = (foundRCS || foundCVS) ? false : !SVN::findFile(fn).empty(); + bool foundGIT = (foundRCS || foundCVS || foundSVN) ? false : !GIT::findFile(fn).empty(); + if (foundRCS || foundCVS || foundSVN || foundGIT) { + docstring const file = makeDisplayPath(fn.absFileName(), 20); + docstring const text = + bformat(_("Do you want to retrieve the document" + " %1$s from version control?"), file); + int const ret = Alert::prompt(_("Retrieve from version control?"), + text, 0, 1, _("&Retrieve"), _("&Cancel")); + + if (ret == 0) { + // Since the retrieve commands are implemented using + // more general update commands we need to ensure that + // we do not change an existing file by accident. + if (fn.exists()) + return false; + if (foundRCS) + return RCS::retrieve(fn); + else if (foundCVS) + return CVS::retrieve(fn); + else if (foundSVN) + return SVN::retrieve(fn); + else + return GIT::retrieve(fn); + } + } return false; } @@ -90,116 +139,214 @@ void LyXVC::setBuffer(Buffer * buf) } -void LyXVC::registrer() +bool LyXVC::registrer() { - FileName const filename(owner_->absFileName()); + FileName const filename = owner_->fileName(); // there must be a file to save - if (!filename.isFileReadable()) { + if (!filename.isReadableFile()) { Alert::error(_("Document not saved"), _("You must save the document " "before it can be registered.")); - return; + return false; } // it is very likely here that the vcs is not created yet... if (!vcs) { - FileName const cvs_entries(makeAbsPath("CVS/Entries")); - - if (cvs_entries.isFileReadable()) { - LYXERR(Debug::LYXVC) - << "LyXVC: registering " - << to_utf8(makeDisplayPath(filename.absFilename())) - << " with CVS" << endl; - vcs.reset(new CVS(cvs_entries, filename)); + //check in the root directory of the document + FileName const cvs_entries(onlyPath(filename.absFileName()) + "/CVS/Entries"); + FileName const svn_entries(onlyPath(filename.absFileName()) + "/.svn/entries"); + FileName const git_index(onlyPath(filename.absFileName()) + "/.git/index"); + + if (git_index.isReadableFile()) { + LYXERR(Debug::LYXVC, "LyXVC: registering " + << to_utf8(filename.displayName()) << " with GIT"); + vcs.reset(new GIT(git_index, owner_)); + + } else if (svn_entries.isReadableFile()) { + LYXERR(Debug::LYXVC, "LyXVC: registering " + << to_utf8(filename.displayName()) << " with SVN"); + vcs.reset(new SVN(svn_entries, owner_)); + + } else if (cvs_entries.isReadableFile()) { + LYXERR(Debug::LYXVC, "LyXVC: registering " + << to_utf8(filename.displayName()) << " with CVS"); + vcs.reset(new CVS(cvs_entries, owner_)); } else { - LYXERR(Debug::LYXVC) - << "LyXVC: registering " - << to_utf8(makeDisplayPath(filename.absFilename())) - << " with RCS" << endl; - vcs.reset(new RCS(filename)); + LYXERR(Debug::LYXVC, "LyXVC: registering " + << to_utf8(filename.displayName()) << " with RCS"); + vcs.reset(new RCS(FileName(), owner_)); } - - vcs->owner(owner_); } - LYXERR(Debug::LYXVC) << "LyXVC: registrer" << endl; - pair tmp = - Alert::askForText(_("LyX VC: Initial description"), - _("(no initial description)")); - if (!tmp.first || tmp.second.empty()) { - // should we insist on checking tmp.second.empty()? - LYXERR(Debug::LYXVC) << "LyXVC: user cancelled" << endl; - return; + LYXERR(Debug::LYXVC, "LyXVC: registrer"); + docstring response; + bool ok = Alert::askForText(response, _("LyX VC: Initial description"), + _("(no initial description)")); + if (!ok) { + LYXERR(Debug::LYXVC, "LyXVC: user cancelled"); + vcs.reset(0); + return false; } + if (response.empty()) + response = _("(no initial description)"); + vcs->registrer(to_utf8(response)); + return true; +} + - vcs->registrer(to_utf8(tmp.second)); +string LyXVC::rename(FileName const & fn) +{ + LYXERR(Debug::LYXVC, "LyXVC: rename"); + if (!vcs || fileInVC(fn)) + return string(); + docstring response; + bool ok = Alert::askForText(response, _("LyX VC: Log message"), + _("(no log message)")); + if (!ok) { + LYXERR(Debug::LYXVC, "LyXVC: user cancelled"); + return string(); + } + if (response.empty()) + response = _("(no log message)"); + string ret = vcs->rename(fn, to_utf8(response)); + return ret; } -void LyXVC::checkIn() +string LyXVC::copy(FileName const & fn) { + LYXERR(Debug::LYXVC, "LyXVC: copy"); + if (!vcs || fileInVC(fn)) + return string(); + docstring response; + bool ok = Alert::askForText(response, _("LyX VC: Log message"), + _("(no log message)")); + if (!ok) { + LYXERR(Debug::LYXVC, "LyXVC: user cancelled"); + return string(); + } + if (response.empty()) + response = _("(no log message)"); + string ret = vcs->copy(fn, to_utf8(response)); + return ret; +} - LYXERR(Debug::LYXVC) << "LyXVC: checkIn" << endl; - pair tmp = Alert::askForText(_("LyX VC: Log Message")); - if (tmp.first) { - if (tmp.second.empty()) { - tmp.second = _("(no log message)"); - } - vcs->checkIn(to_utf8(tmp.second)); + +LyXVC::CommandResult LyXVC::checkIn(string & log) +{ + LYXERR(Debug::LYXVC, "LyXVC: checkIn"); + if (!vcs) + return ErrorBefore; + docstring empty(_("(no log message)")); + docstring response; + bool ok = true; + if (vcs->isCheckInWithConfirmation()) + ok = Alert::askForText(response, _("LyX VC: Log Message")); + if (ok) { + if (response.empty()) + response = empty; + //shell collisions + response = subst(response, from_ascii("\""), from_ascii("\\\"")); + return vcs->checkIn(to_utf8(response), log); } else { - LYXERR(Debug::LYXVC) << "LyXVC: user cancelled" << endl; + LYXERR(Debug::LYXVC, "LyXVC: user cancelled"); + return Cancelled; } } -void LyXVC::checkOut() +string LyXVC::checkOut() { - LYXERR(Debug::LYXVC) << "LyXVC: checkOut" << endl; + if (!vcs) + return string(); + //RCS allows checkOut only in ReadOnly mode + if (vcs->toggleReadOnlyEnabled() && !owner_->hasReadonlyFlag()) + return string(); - vcs->checkOut(); + LYXERR(Debug::LYXVC, "LyXVC: checkOut"); + return vcs->checkOut(); } -void LyXVC::revert() +string LyXVC::repoUpdate() { - LYXERR(Debug::LYXVC) << "LyXVC: revert" << endl; + LYXERR(Debug::LYXVC, "LyXVC: repoUpdate"); + if (!vcs) + return string(); + return vcs->repoUpdate(); +} - docstring const file = makeDisplayPath(owner_->absFileName(), 20); - docstring text = bformat(_("Reverting to the stored version of the " - "document %1$s will lose all current changes.\n\n" - "Do you want to revert to the saved version?"), file); - int const ret = Alert::prompt(_("Revert to stored version of document?"), - text, 0, 1, _("&Revert"), _("&Cancel")); - if (ret == 0) - vcs->revert(); +string LyXVC::lockingToggle() +{ + LYXERR(Debug::LYXVC, "LyXVC: toggle locking property"); + if (!vcs) + return string(); + return vcs->lockingToggle(); +} + + +bool LyXVC::revert() +{ + LYXERR(Debug::LYXVC, "LyXVC: revert"); + if (!vcs) + return false; + + docstring const file = owner_->fileName().displayName(20); + docstring text = bformat(_("Reverting to the stored version of the " + "document %1$s will lose all current changes.\n\n" + "Do you want to revert to the older version?"), file); + int ret = 0; + if (vcs->isRevertWithConfirmation()) + ret = Alert::prompt(_("Revert to stored version of document?"), + text, 0, 1, _("&Revert"), _("&Cancel")); + + return ret == 0 && vcs->revert(); } void LyXVC::undoLast() { + if (!vcs) + return; vcs->undoLast(); } -void LyXVC::toggleReadOnly() +string LyXVC::toggleReadOnly() { + if (!vcs) + return string(); + if (!vcs->toggleReadOnlyEnabled()) + return string(); + switch (vcs->status()) { case VCS::UNLOCKED: - LYXERR(Debug::LYXVC) << "LyXVC: toggle to locked" << endl; - checkOut(); - break; - case VCS::LOCKED: - LYXERR(Debug::LYXVC) << "LyXVC: toggle to unlocked" << endl; - checkIn(); - break; + LYXERR(Debug::LYXVC, "LyXVC: toggle to locked"); + return checkOut(); + case VCS::LOCKED: { + LYXERR(Debug::LYXVC, "LyXVC: toggle to unlocked"); + string log; + if (checkIn(log) != VCSuccess) + return string(); + return log; } + case VCS::NOLOCKING: + Buffer * b = vcs->owner(); + bool const newstate = !b->hasReadonlyFlag(); + string result = "LyXVC: toggle to "; + result += (newstate ? "readonly" : "readwrite"); + LYXERR(Debug::LYXVC, result); + b->setReadonly(newstate); + return result; + } + return string(); } -bool LyXVC::inUse() +bool LyXVC::inUse() const { if (vcs) return true; @@ -207,21 +354,19 @@ bool LyXVC::inUse() } -//string const & LyXVC::version() const -//{ -// return vcs->version(); -//} - - string const LyXVC::versionString() const { + if (!vcs) + return string(); return vcs->versionString(); } -string const & LyXVC::locker() const +bool LyXVC::locking() const { - return vcs->locker(); + if (!vcs) + return false; + return vcs->status() != VCS::NOLOCKING; } @@ -230,16 +375,89 @@ string const LyXVC::getLogFile() const if (!vcs) return string(); - FileName const tmpf(tempName(FileName(), "lyxvclog")); + TempFile tempfile("lyxvclog"); + tempfile.setAutoRemove(false); + FileName const tmpf = tempfile.name(); if (tmpf.empty()) { - LYXERR(Debug::LYXVC) << "Could not generate logfile " - << tmpf << endl; + LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf); return string(); } - LYXERR(Debug::LYXVC) << "Generating logfile " << tmpf << endl; + LYXERR(Debug::LYXVC, "Generating logfile " << tmpf); vcs->getLog(tmpf); - return tmpf.absFilename(); + return tmpf.absFileName(); +} + + +string LyXVC::revisionInfo(RevisionInfo const info) const +{ + if (!vcs) + return string(); + + return vcs->revisionInfo(info); +} + + +bool LyXVC::renameEnabled() const +{ + if (!inUse()) + return false; + return vcs->renameEnabled(); +} + + +bool LyXVC::copyEnabled() const +{ + if (!inUse()) + return false; + return vcs->copyEnabled(); +} + + +bool LyXVC::checkOutEnabled() const +{ + return vcs && vcs->checkOutEnabled(); +} + + +bool LyXVC::checkInEnabled() const +{ + return vcs && vcs->checkInEnabled(); } +bool LyXVC::isCheckInWithConfirmation() const +{ + return vcs && vcs->isCheckInWithConfirmation(); +} + + +bool LyXVC::lockingToggleEnabled() const +{ + return vcs && vcs->lockingToggleEnabled(); +} + + +bool LyXVC::undoLastEnabled() const +{ + return vcs && vcs->undoLastEnabled(); +} + + +bool LyXVC::repoUpdateEnabled() const +{ + return vcs && vcs->repoUpdateEnabled(); +} + + +bool LyXVC::prepareFileRevision(string const & rev, std::string & f) +{ + return vcs && vcs->prepareFileRevision(rev, f); +} + + +bool LyXVC::prepareFileRevisionEnabled() +{ + return vcs && vcs->prepareFileRevisionEnabled(); +} + } // namespace lyx