3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
7 * \author Jean-Marc Lasgouttes
8 * \author Angus Leeming
10 * \author André Pönitz
13 * Full author contact details are available in file CREDITS.
19 #include "VCBackend.h"
22 #include "frontends/alert.h"
24 #include "support/debug.h"
25 #include "support/filetools.h"
26 #include "support/gettext.h"
27 #include "support/lstrings.h"
30 using namespace lyx::support;
34 namespace Alert = frontend::Alert;
43 // for the sake of boost::scoped_ptr
48 bool LyXVC::fileInVC(FileName const & fn)
50 if (!RCS::findFile(fn).empty())
52 if (!CVS::findFile(fn).empty())
54 if (!SVN::findFile(fn).empty())
56 if (!GIT::findFile(fn).empty())
62 bool LyXVC::file_found_hook(FileName const & fn)
65 // Check if file is under RCS
66 if (!(found_file = RCS::findFile(fn)).empty()) {
67 vcs.reset(new RCS(found_file, owner_));
70 // Check if file is under CVS
71 if (!(found_file = CVS::findFile(fn)).empty()) {
72 vcs.reset(new CVS(found_file, owner_));
75 // Check if file is under SVN
76 if (!(found_file = SVN::findFile(fn)).empty()) {
77 vcs.reset(new SVN(found_file, owner_));
80 // Check if file is under GIT
81 if (!(found_file = GIT::findFile(fn)).empty()) {
82 vcs.reset(new GIT(found_file, owner_));
86 // file is not under any VCS.
92 bool LyXVC::file_not_found_hook(FileName const & fn)
94 // Check if file is under RCS.
95 // This happens if we are trying to load non existent
96 // file on disk, but existent in ,v version.
97 bool foundRCS = !RCS::findFile(fn).empty();
98 bool foundCVS = foundRCS ? false : !CVS::findFile(fn).empty();
99 bool foundSVN = (foundRCS || foundCVS) ? false : !SVN::findFile(fn).empty();
100 bool foundGIT = (foundRCS || foundCVS || foundSVN) ? false : !GIT::findFile(fn).empty();
101 if (foundRCS || foundCVS || foundSVN || foundGIT) {
102 docstring const file = makeDisplayPath(fn.absFileName(), 20);
103 docstring const text =
104 bformat(_("Do you want to retrieve the document"
105 " %1$s from version control?"), file);
106 int const ret = Alert::prompt(_("Retrieve from version control?"),
107 text, 0, 1, _("&Retrieve"), _("&Cancel"));
110 // Since the retrieve commands are implemented using
111 // more general update commands we need to ensure that
112 // we do not change an existing file by accident.
116 return RCS::retrieve(fn);
118 return CVS::retrieve(fn);
120 return SVN::retrieve(fn);
122 return GIT::retrieve(fn);
129 void LyXVC::setBuffer(Buffer * buf)
135 bool LyXVC::registrer()
137 FileName const filename = owner_->fileName();
139 // there must be a file to save
140 if (!filename.isReadableFile()) {
141 Alert::error(_("Document not saved"),
142 _("You must save the document "
143 "before it can be registered."));
147 // it is very likely here that the vcs is not created yet...
149 //check in the root directory of the document
150 FileName const cvs_entries(onlyPath(filename.absFileName()) + "/CVS/Entries");
151 FileName const svn_entries(onlyPath(filename.absFileName()) + "/.svn/entries");
152 FileName const git_index(onlyPath(filename.absFileName()) + "/.git/index");
154 if (git_index.isReadableFile()) {
155 LYXERR(Debug::LYXVC, "LyXVC: registering "
156 << to_utf8(filename.displayName()) << " with GIT");
157 vcs.reset(new GIT(git_index, owner_));
159 } else if (svn_entries.isReadableFile()) {
160 LYXERR(Debug::LYXVC, "LyXVC: registering "
161 << to_utf8(filename.displayName()) << " with SVN");
162 vcs.reset(new SVN(svn_entries, owner_));
164 } else if (cvs_entries.isReadableFile()) {
165 LYXERR(Debug::LYXVC, "LyXVC: registering "
166 << to_utf8(filename.displayName()) << " with CVS");
167 vcs.reset(new CVS(cvs_entries, owner_));
170 LYXERR(Debug::LYXVC, "LyXVC: registering "
171 << to_utf8(filename.displayName()) << " with RCS");
172 vcs.reset(new RCS(FileName(), owner_));
176 LYXERR(Debug::LYXVC, "LyXVC: registrer");
178 bool ok = Alert::askForText(response, _("LyX VC: Initial description"),
179 _("(no initial description)"));
181 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
185 if (response.empty())
186 response = _("(no initial description)");
187 vcs->registrer(to_utf8(response));
192 string LyXVC::rename(FileName const & fn)
194 LYXERR(Debug::LYXVC, "LyXVC: rename");
195 if (!vcs || fileInVC(fn))
198 bool ok = Alert::askForText(response, _("LyX VC: Log message"),
199 _("(no log message)"));
201 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
204 if (response.empty())
205 response = _("(no log message)");
206 string ret = vcs->rename(fn, to_utf8(response));
211 string LyXVC::copy(FileName const & fn)
213 LYXERR(Debug::LYXVC, "LyXVC: copy");
214 if (!vcs || fileInVC(fn))
217 bool ok = Alert::askForText(response, _("LyX VC: Log message"),
218 _("(no log message)"));
220 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
223 if (response.empty())
224 response = _("(no log message)");
225 string ret = vcs->copy(fn, to_utf8(response));
230 LyXVC::CommandResult LyXVC::checkIn(string & log)
232 LYXERR(Debug::LYXVC, "LyXVC: checkIn");
235 docstring empty(_("(no log message)"));
238 if (vcs->isCheckInWithConfirmation())
239 ok = Alert::askForText(response, _("LyX VC: Log Message"));
241 if (response.empty())
244 response = subst(response, from_ascii("\""), from_ascii("\\\""));
245 return vcs->checkIn(to_utf8(response), log);
247 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
253 string LyXVC::checkOut()
257 //RCS allows checkOut only in ReadOnly mode
258 if (vcs->toggleReadOnlyEnabled() && !owner_->isReadonly())
261 LYXERR(Debug::LYXVC, "LyXVC: checkOut");
262 return vcs->checkOut();
266 string LyXVC::repoUpdate()
268 LYXERR(Debug::LYXVC, "LyXVC: repoUpdate");
271 return vcs->repoUpdate();
275 string LyXVC::lockingToggle()
277 LYXERR(Debug::LYXVC, "LyXVC: toggle locking property");
280 return vcs->lockingToggle();
286 LYXERR(Debug::LYXVC, "LyXVC: revert");
290 docstring const file = owner_->fileName().displayName(20);
291 docstring text = bformat(_("Reverting to the stored version of the "
292 "document %1$s will lose all current changes.\n\n"
293 "Do you want to revert to the older version?"), file);
295 if (vcs->isRevertWithConfirmation())
296 ret = Alert::prompt(_("Revert to stored version of document?"),
297 text, 0, 1, _("&Revert"), _("&Cancel"));
299 return ret == 0 && vcs->revert();
303 void LyXVC::undoLast()
311 string LyXVC::toggleReadOnly()
315 if (!vcs->toggleReadOnlyEnabled())
318 switch (vcs->status()) {
320 LYXERR(Debug::LYXVC, "LyXVC: toggle to locked");
323 LYXERR(Debug::LYXVC, "LyXVC: toggle to unlocked");
325 if (checkIn(log) != VCSuccess)
336 bool LyXVC::inUse() const
344 string const LyXVC::versionString() const
348 return vcs->versionString();
352 bool LyXVC::locking() const
356 return vcs->status() != VCS::NOLOCKING;
360 string const LyXVC::getLogFile() const
365 FileName const tmpf = FileName::tempName("lyxvclog");
367 LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
370 LYXERR(Debug::LYXVC, "Generating logfile " << tmpf);
372 return tmpf.absFileName();
376 string LyXVC::revisionInfo(RevisionInfo const info) const
381 return vcs->revisionInfo(info);
385 bool LyXVC::renameEnabled() const
389 return vcs->renameEnabled();
393 bool LyXVC::copyEnabled() const
397 return vcs->copyEnabled();
401 bool LyXVC::checkOutEnabled() const
403 return vcs && vcs->checkOutEnabled();
407 bool LyXVC::checkInEnabled() const
409 return vcs && vcs->checkInEnabled();
413 bool LyXVC::isCheckInWithConfirmation() const
415 return vcs && vcs->isCheckInWithConfirmation();
419 bool LyXVC::lockingToggleEnabled() const
421 return vcs && vcs->lockingToggleEnabled();
425 bool LyXVC::undoLastEnabled() const
427 return vcs && vcs->undoLastEnabled();
431 bool LyXVC::repoUpdateEnabled() const
433 return vcs && vcs->repoUpdateEnabled();
437 bool LyXVC::prepareFileRevision(string const & rev, std::string & f)
439 return vcs && vcs->prepareFileRevision(rev, f);
443 bool LyXVC::prepareFileRevisionEnabled()
445 return vcs && vcs->prepareFileRevisionEnabled();