]> git.lyx.org Git - lyx.git/blob - src/LyXVC.cpp
Natbib authoryear uses (Ref1; Ref2) by default.
[lyx.git] / src / LyXVC.cpp
1 /**
2  * \file LyXVC.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author Jean-Marc Lasgouttes
8  * \author Angus Leeming
9  * \author John Levon
10  * \author André Pönitz
11  * \author Allan Rae
12  *
13  * Full author contact details are available in file CREDITS.
14  */
15
16 #include <config.h>
17
18 #include "LyXVC.h"
19 #include "VCBackend.h"
20 #include "Buffer.h"
21
22 #include "frontends/alert.h"
23
24 #include "support/debug.h"
25 #include "support/filetools.h"
26 #include "support/gettext.h"
27 #include "support/lstrings.h"
28
29 using namespace std;
30 using namespace lyx::support;
31
32 namespace lyx {
33
34 namespace Alert = frontend::Alert;
35
36
37 LyXVC::LyXVC()
38 {
39         owner_ = 0;
40 }
41
42
43 // for the sake of boost::scoped_ptr
44 LyXVC::~LyXVC()
45 {}
46
47
48 bool LyXVC::fileInVC(FileName const & fn)
49 {
50         if (!RCS::findFile(fn).empty())
51                 return true;
52         if (!CVS::findFile(fn).empty())
53                 return true;
54         if (!SVN::findFile(fn).empty())
55                 return true;
56         if (!GIT::findFile(fn).empty())
57                 return true;
58         return false;
59 }
60
61
62 bool LyXVC::file_found_hook(FileName const & fn)
63 {
64         FileName found_file;
65         // Check if file is under RCS
66         if (!(found_file = RCS::findFile(fn)).empty()) {
67                 vcs.reset(new RCS(found_file, owner_));
68                 return true;
69         }
70         // Check if file is under CVS
71         if (!(found_file = CVS::findFile(fn)).empty()) {
72                 vcs.reset(new CVS(found_file, owner_));
73                 return true;
74         }
75         // Check if file is under SVN
76         if (!(found_file = SVN::findFile(fn)).empty()) {
77                 vcs.reset(new SVN(found_file, owner_));
78                 return true;
79         }
80         // Check if file is under GIT
81         if (!(found_file = GIT::findFile(fn)).empty()) {
82                 vcs.reset(new GIT(found_file, owner_));
83                 return true;
84         }
85
86         // file is not under any VCS.
87         vcs.reset(0);
88         return false;
89 }
90
91
92 bool LyXVC::file_not_found_hook(FileName const & fn)
93 {
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"));
108
109                 if (ret == 0) {
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.
113                         if (fn.exists())
114                                 return false;
115                         if (foundRCS)
116                                 return RCS::retrieve(fn);
117                         else if (foundCVS)
118                                 return CVS::retrieve(fn);
119                         else if (foundSVN)
120                                 return SVN::retrieve(fn);
121                         else
122                                 return GIT::retrieve(fn);
123                 }
124         }
125         return false;
126 }
127
128
129 void LyXVC::setBuffer(Buffer * buf)
130 {
131         owner_ = buf;
132 }
133
134
135 bool LyXVC::registrer()
136 {
137         FileName const filename = owner_->fileName();
138
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."));
144                 return false;
145         }
146
147         // it is very likely here that the vcs is not created yet...
148         if (!vcs) {
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");
153
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_));
158
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_));
163
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_));
168
169                 } else {
170                         LYXERR(Debug::LYXVC, "LyXVC: registering "
171                                 << to_utf8(filename.displayName()) << " with RCS");
172                         vcs.reset(new RCS(FileName(), owner_));
173                 }
174         }
175
176         LYXERR(Debug::LYXVC, "LyXVC: registrer");
177         docstring response;
178         bool ok = Alert::askForText(response, _("LyX VC: Initial description"),
179                         _("(no initial description)"));
180         if (!ok) {
181                 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
182                 vcs.reset(0);
183                 return false;
184         }
185         if (response.empty())
186                 response = _("(no initial description)");
187         vcs->registrer(to_utf8(response));
188         return true;
189 }
190
191
192 string LyXVC::rename(FileName const & fn)
193 {
194         LYXERR(Debug::LYXVC, "LyXVC: rename");
195         if (!vcs || fileInVC(fn))
196                 return string();
197         docstring response;
198         bool ok = Alert::askForText(response, _("LyX VC: Log message"),
199                         _("(no log message)"));
200         if (!ok) {
201                 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
202                 return string();
203         }
204         if (response.empty())
205                 response = _("(no log message)");
206         string ret = vcs->rename(fn, to_utf8(response));
207         return ret;
208 }
209
210
211 string LyXVC::copy(FileName const & fn)
212 {
213         LYXERR(Debug::LYXVC, "LyXVC: copy");
214         if (!vcs || fileInVC(fn))
215                 return string();
216         docstring response;
217         bool ok = Alert::askForText(response, _("LyX VC: Log message"),
218                         _("(no log message)"));
219         if (!ok) {
220                 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
221                 return string();
222         }
223         if (response.empty())
224                 response = _("(no log message)");
225         string ret = vcs->copy(fn, to_utf8(response));
226         return ret;
227 }
228
229
230 LyXVC::CommandResult LyXVC::checkIn(string & log)
231 {
232         LYXERR(Debug::LYXVC, "LyXVC: checkIn");
233         if (!vcs)
234                 return ErrorBefore;
235         docstring empty(_("(no log message)"));
236         docstring response;
237         bool ok = true;
238         if (vcs->isCheckInWithConfirmation())
239                 ok = Alert::askForText(response, _("LyX VC: Log Message"));
240         if (ok) {
241                 if (response.empty())
242                         response = empty;
243                 //shell collisions
244                 response = subst(response, from_ascii("\""), from_ascii("\\\""));
245                 return vcs->checkIn(to_utf8(response), log);
246         } else {
247                 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
248                 return Cancelled;
249         }
250 }
251
252
253 string LyXVC::checkOut()
254 {
255         if (!vcs)
256                 return string();
257         //RCS allows checkOut only in ReadOnly mode
258         if (vcs->toggleReadOnlyEnabled() && !owner_->isReadonly())
259                 return string();
260
261         LYXERR(Debug::LYXVC, "LyXVC: checkOut");
262         return vcs->checkOut();
263 }
264
265
266 string LyXVC::repoUpdate()
267 {
268         LYXERR(Debug::LYXVC, "LyXVC: repoUpdate");
269         if (!vcs)
270                 return string();
271         return vcs->repoUpdate();
272 }
273
274
275 string LyXVC::lockingToggle()
276 {
277         LYXERR(Debug::LYXVC, "LyXVC: toggle locking property");
278         if (!vcs)
279                 return string();
280         return vcs->lockingToggle();
281 }
282
283
284 bool LyXVC::revert()
285 {
286         LYXERR(Debug::LYXVC, "LyXVC: revert");
287         if (!vcs)
288                 return false;
289
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);
294         int ret = 0;
295         if (vcs->isRevertWithConfirmation())
296                 ret = Alert::prompt(_("Revert to stored version of document?"),
297                         text, 0, 1, _("&Revert"), _("&Cancel"));
298
299         return ret == 0 && vcs->revert();
300 }
301
302
303 void LyXVC::undoLast()
304 {
305         if (!vcs)
306                 return;
307         vcs->undoLast();
308 }
309
310
311 string LyXVC::toggleReadOnly()
312 {
313         if (!vcs)
314                 return string();
315         if (!vcs->toggleReadOnlyEnabled())
316                 return string();
317
318         switch (vcs->status()) {
319         case VCS::UNLOCKED:
320                 LYXERR(Debug::LYXVC, "LyXVC: toggle to locked");
321                 return checkOut();
322         case VCS::LOCKED: {
323                 LYXERR(Debug::LYXVC, "LyXVC: toggle to unlocked");
324                 string log;
325                 if (checkIn(log) != VCSuccess)
326                         return string();
327                 return log;
328         }
329         case VCS::NOLOCKING:
330                 break;
331         }
332         return string();
333 }
334
335
336 bool LyXVC::inUse() const
337 {
338         if (vcs)
339                 return true;
340         return false;
341 }
342
343
344 string const LyXVC::versionString() const
345 {
346         if (!vcs)
347                 return string();
348         return vcs->versionString();
349 }
350
351
352 bool LyXVC::locking() const
353 {
354         if (!vcs)
355                 return false;
356         return vcs->status() != VCS::NOLOCKING;
357 }
358
359
360 string const LyXVC::getLogFile() const
361 {
362         if (!vcs)
363                 return string();
364
365         FileName const tmpf = FileName::tempName("lyxvclog");
366         if (tmpf.empty()) {
367                 LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
368                 return string();
369         }
370         LYXERR(Debug::LYXVC, "Generating logfile " << tmpf);
371         vcs->getLog(tmpf);
372         return tmpf.absFileName();
373 }
374
375
376 string LyXVC::revisionInfo(RevisionInfo const info) const
377 {
378         if (!vcs)
379                 return string();
380
381         return vcs->revisionInfo(info);
382 }
383
384
385 bool LyXVC::renameEnabled() const
386 {
387         if (!inUse())
388                 return false;
389         return vcs->renameEnabled();
390 }
391
392
393 bool LyXVC::copyEnabled() const
394 {
395         if (!inUse())
396                 return false;
397         return vcs->copyEnabled();
398 }
399
400
401 bool LyXVC::checkOutEnabled() const
402 {
403         return vcs && vcs->checkOutEnabled();
404 }
405
406
407 bool LyXVC::checkInEnabled() const
408 {
409         return vcs && vcs->checkInEnabled();
410 }
411
412
413 bool LyXVC::isCheckInWithConfirmation() const
414 {
415         return vcs && vcs->isCheckInWithConfirmation();
416 }
417
418
419 bool LyXVC::lockingToggleEnabled() const
420 {
421         return vcs && vcs->lockingToggleEnabled();
422 }
423
424
425 bool LyXVC::undoLastEnabled() const
426 {
427         return vcs && vcs->undoLastEnabled();
428 }
429
430
431 bool LyXVC::repoUpdateEnabled() const
432 {
433         return vcs && vcs->repoUpdateEnabled();
434 }
435         
436         
437 bool LyXVC::prepareFileRevision(string const & rev, std::string & f)
438 {
439         return vcs && vcs->prepareFileRevision(rev, f);
440 }
441
442
443 bool LyXVC::prepareFileRevisionEnabled()
444 {
445         return vcs && vcs->prepareFileRevisionEnabled();
446 }
447
448 } // namespace lyx