]> git.lyx.org Git - lyx.git/blob - src/LyXVC.cpp
Merge branch 'master' of git.lyx.org:lyx
[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 #include "support/TempFile.h"
29
30 using namespace std;
31 using namespace lyx::support;
32
33 namespace lyx {
34
35 namespace Alert = frontend::Alert;
36
37
38 LyXVC::LyXVC()
39 {
40         owner_ = 0;
41 }
42
43
44 bool LyXVC::fileInVC(FileName const & fn)
45 {
46         if (!RCS::findFile(fn).empty())
47                 return true;
48         if (!CVS::findFile(fn).empty())
49                 return true;
50         if (!SVN::findFile(fn).empty())
51                 return true;
52         if (!GIT::findFile(fn).empty())
53                 return true;
54         return false;
55 }
56
57
58 bool LyXVC::file_found_hook(FileName const & fn)
59 {
60         FileName found_file;
61         // Check if file is under RCS
62         if (!(found_file = RCS::findFile(fn)).empty()) {
63                 vcs.reset(new RCS(found_file, owner_));
64                 return true;
65         }
66         // Check if file is under CVS
67         if (!(found_file = CVS::findFile(fn)).empty()) {
68                 vcs.reset(new CVS(found_file, owner_));
69                 return true;
70         }
71         // Check if file is under SVN
72         if (!(found_file = SVN::findFile(fn)).empty()) {
73                 vcs.reset(new SVN(found_file, owner_));
74                 return true;
75         }
76         // Check if file is under GIT
77         if (!(found_file = GIT::findFile(fn)).empty()) {
78                 vcs.reset(new GIT(found_file, owner_));
79                 return true;
80         }
81
82         // file is not under any VCS.
83         vcs.reset(0);
84         return false;
85 }
86
87
88 bool LyXVC::file_not_found_hook(FileName const & fn)
89 {
90         // Check if file is under RCS.
91         // This happens if we are trying to load non existent
92         // file on disk, but existent in ,v version.
93         bool foundRCS = !RCS::findFile(fn).empty();
94         bool foundCVS = foundRCS ? false : !CVS::findFile(fn).empty();
95         bool foundSVN = (foundRCS || foundCVS) ? false : !SVN::findFile(fn).empty();
96         bool foundGIT = (foundRCS || foundCVS || foundSVN) ? false : !GIT::findFile(fn).empty();
97         if (foundRCS || foundCVS || foundSVN || foundGIT) {
98                 docstring const file = makeDisplayPath(fn.absFileName(), 20);
99                 docstring const text =
100                         bformat(_("Do you want to retrieve the document"
101                                                    " %1$s from version control?"), file);
102                 int const ret = Alert::prompt(_("Retrieve from version control?"),
103                         text, 0, 1, _("&Retrieve"), _("&Cancel"));
104
105                 if (ret == 0) {
106                         // Since the retrieve commands are implemented using
107                         // more general update commands we need to ensure that
108                         // we do not change an existing file by accident.
109                         if (fn.exists())
110                                 return false;
111                         if (foundRCS)
112                                 return RCS::retrieve(fn);
113                         else if (foundCVS)
114                                 return CVS::retrieve(fn);
115                         else if (foundSVN)
116                                 return SVN::retrieve(fn);
117                         else
118                                 return GIT::retrieve(fn);
119                 }
120         }
121         return false;
122 }
123
124
125 void LyXVC::setBuffer(Buffer * buf)
126 {
127         owner_ = buf;
128 }
129
130
131 bool LyXVC::registrer()
132 {
133         FileName const filename = owner_->fileName();
134
135         // there must be a file to save
136         if (!filename.isReadableFile()) {
137                 Alert::error(_("Document not saved"),
138                              _("You must save the document "
139                                             "before it can be registered."));
140                 return false;
141         }
142
143         // it is very likely here that the vcs is not created yet...
144         if (!vcs) {
145                 //check in the root directory of the document
146                 FileName const cvs_entries(onlyPath(filename.absFileName()) + "/CVS/Entries");
147                 FileName const svn_entries(onlyPath(filename.absFileName()) + "/.svn/entries");
148                 FileName const git_index(onlyPath(filename.absFileName()) + "/.git/index");
149
150                 if (git_index.isReadableFile()) {
151                         LYXERR(Debug::LYXVC, "LyXVC: registering "
152                                 << to_utf8(filename.displayName()) << " with GIT");
153                         vcs.reset(new GIT(git_index, owner_));
154
155                 } else if (svn_entries.isReadableFile()) {
156                         LYXERR(Debug::LYXVC, "LyXVC: registering "
157                                 << to_utf8(filename.displayName()) << " with SVN");
158                         vcs.reset(new SVN(svn_entries, owner_));
159
160                 } else if (cvs_entries.isReadableFile()) {
161                         LYXERR(Debug::LYXVC, "LyXVC: registering "
162                                 << to_utf8(filename.displayName()) << " with CVS");
163                         vcs.reset(new CVS(cvs_entries, owner_));
164
165                 } else {
166                         LYXERR(Debug::LYXVC, "LyXVC: registering "
167                                 << to_utf8(filename.displayName()) << " with RCS");
168                         vcs.reset(new RCS(FileName(), owner_));
169                 }
170         }
171
172         LYXERR(Debug::LYXVC, "LyXVC: registrer");
173         docstring response;
174         bool ok = Alert::askForText(response, _("LyX VC: Initial description"),
175                         _("(no initial description)"));
176         if (!ok) {
177                 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
178                 vcs.reset(0);
179                 return false;
180         }
181         if (response.empty())
182                 response = _("(no initial description)");
183         vcs->registrer(to_utf8(response));
184         return true;
185 }
186
187
188 string LyXVC::rename(FileName const & fn)
189 {
190         LYXERR(Debug::LYXVC, "LyXVC: rename");
191         if (!vcs || fileInVC(fn))
192                 return string();
193         docstring response;
194         bool ok = Alert::askForText(response, _("LyX VC: Log message"),
195                         _("(no log message)"));
196         if (!ok) {
197                 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
198                 return string();
199         }
200         if (response.empty())
201                 response = _("(no log message)");
202         string ret = vcs->rename(fn, to_utf8(response));
203         return ret;
204 }
205
206
207 string LyXVC::copy(FileName const & fn)
208 {
209         LYXERR(Debug::LYXVC, "LyXVC: copy");
210         if (!vcs || fileInVC(fn))
211                 return string();
212         docstring response;
213         bool ok = Alert::askForText(response, _("LyX VC: Log message"),
214                         _("(no log message)"));
215         if (!ok) {
216                 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
217                 return string();
218         }
219         if (response.empty())
220                 response = _("(no log message)");
221         string ret = vcs->copy(fn, to_utf8(response));
222         return ret;
223 }
224
225
226 LyXVC::CommandResult LyXVC::checkIn(string & log)
227 {
228         LYXERR(Debug::LYXVC, "LyXVC: checkIn");
229         if (!vcs)
230                 return ErrorBefore;
231         docstring empty(_("(no log message)"));
232         docstring response;
233         bool ok = true;
234         if (vcs->isCheckInWithConfirmation())
235                 ok = Alert::askForText(response, _("LyX VC: Log Message"));
236         if (ok) {
237                 if (response.empty())
238                         response = empty;
239                 //shell collisions
240                 response = subst(response, from_ascii("\""), from_ascii("\\\""));
241                 return vcs->checkIn(to_utf8(response), log);
242         } else {
243                 LYXERR(Debug::LYXVC, "LyXVC: user cancelled");
244                 return Cancelled;
245         }
246 }
247
248
249 string LyXVC::checkOut()
250 {
251         if (!vcs)
252                 return string();
253         //RCS allows checkOut only in ReadOnly mode
254         if (vcs->toggleReadOnlyEnabled() && !owner_->isReadonly())
255                 return string();
256
257         LYXERR(Debug::LYXVC, "LyXVC: checkOut");
258         return vcs->checkOut();
259 }
260
261
262 string LyXVC::repoUpdate()
263 {
264         LYXERR(Debug::LYXVC, "LyXVC: repoUpdate");
265         if (!vcs)
266                 return string();
267         return vcs->repoUpdate();
268 }
269
270
271 string LyXVC::lockingToggle()
272 {
273         LYXERR(Debug::LYXVC, "LyXVC: toggle locking property");
274         if (!vcs)
275                 return string();
276         return vcs->lockingToggle();
277 }
278
279
280 bool LyXVC::revert()
281 {
282         LYXERR(Debug::LYXVC, "LyXVC: revert");
283         if (!vcs)
284                 return false;
285
286         docstring const file = owner_->fileName().displayName(20);
287         docstring text = bformat(_("Reverting to the stored version of the "
288                                 "document %1$s will lose all current changes.\n\n"
289                                 "Do you want to revert to the older version?"), file);
290         int ret = 0;
291         if (vcs->isRevertWithConfirmation())
292                 ret = Alert::prompt(_("Revert to stored version of document?"),
293                         text, 0, 1, _("&Revert"), _("&Cancel"));
294
295         return ret == 0 && vcs->revert();
296 }
297
298
299 void LyXVC::undoLast()
300 {
301         if (!vcs)
302                 return;
303         vcs->undoLast();
304 }
305
306
307 string LyXVC::toggleReadOnly()
308 {
309         if (!vcs)
310                 return string();
311         if (!vcs->toggleReadOnlyEnabled())
312                 return string();
313
314         switch (vcs->status()) {
315         case VCS::UNLOCKED:
316                 LYXERR(Debug::LYXVC, "LyXVC: toggle to locked");
317                 return checkOut();
318         case VCS::LOCKED: {
319                 LYXERR(Debug::LYXVC, "LyXVC: toggle to unlocked");
320                 string log;
321                 if (checkIn(log) != VCSuccess)
322                         return string();
323                 return log;
324         }
325         case VCS::NOLOCKING:
326                 Buffer * b = vcs->owner();
327                 bool const newstate = !b->isReadonly();
328                 string result = "LyXVC: toggle to ";
329                 result += (newstate ? "readonly" : "readwrite");
330                 LYXERR(Debug::LYXVC, result);
331                 b->setReadonly(newstate);
332                 return result;
333         }
334         return string();
335 }
336
337
338 bool LyXVC::inUse() const
339 {
340         if (vcs)
341                 return true;
342         return false;
343 }
344
345
346 string const LyXVC::versionString() const
347 {
348         if (!vcs)
349                 return string();
350         return vcs->versionString();
351 }
352
353
354 bool LyXVC::locking() const
355 {
356         if (!vcs)
357                 return false;
358         return vcs->status() != VCS::NOLOCKING;
359 }
360
361
362 string const LyXVC::getLogFile() const
363 {
364         if (!vcs)
365                 return string();
366
367         TempFile tempfile("lyxvclog");
368         tempfile.setAutoRemove(false);
369         FileName const tmpf = tempfile.name();
370         if (tmpf.empty()) {
371                 LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
372                 return string();
373         }
374         LYXERR(Debug::LYXVC, "Generating logfile " << tmpf);
375         vcs->getLog(tmpf);
376         return tmpf.absFileName();
377 }
378
379
380 string LyXVC::revisionInfo(RevisionInfo const info) const
381 {
382         if (!vcs)
383                 return string();
384
385         return vcs->revisionInfo(info);
386 }
387
388
389 bool LyXVC::renameEnabled() const
390 {
391         if (!inUse())
392                 return false;
393         return vcs->renameEnabled();
394 }
395
396
397 bool LyXVC::copyEnabled() const
398 {
399         if (!inUse())
400                 return false;
401         return vcs->copyEnabled();
402 }
403
404
405 bool LyXVC::checkOutEnabled() const
406 {
407         return vcs && vcs->checkOutEnabled();
408 }
409
410
411 bool LyXVC::checkInEnabled() const
412 {
413         return vcs && vcs->checkInEnabled();
414 }
415
416
417 bool LyXVC::isCheckInWithConfirmation() const
418 {
419         return vcs && vcs->isCheckInWithConfirmation();
420 }
421
422
423 bool LyXVC::lockingToggleEnabled() const
424 {
425         return vcs && vcs->lockingToggleEnabled();
426 }
427
428
429 bool LyXVC::undoLastEnabled() const
430 {
431         return vcs && vcs->undoLastEnabled();
432 }
433
434
435 bool LyXVC::repoUpdateEnabled() const
436 {
437         return vcs && vcs->repoUpdateEnabled();
438 }
439         
440         
441 bool LyXVC::prepareFileRevision(string const & rev, std::string & f)
442 {
443         return vcs && vcs->prepareFileRevision(rev, f);
444 }
445
446
447 bool LyXVC::prepareFileRevisionEnabled()
448 {
449         return vcs && vcs->prepareFileRevisionEnabled();
450 }
451
452 } // namespace lyx