]> git.lyx.org Git - lyx.git/blob - src/LyXVC.cpp
GuiTabular: disabling is now done on textChanged()
[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         case VCS::UNVERSIONED:
331                 break;
332         }
333         return string();
334 }
335
336
337 bool LyXVC::inUse() const
338 {
339         if (vcs)
340                 return vcs->status() != VCS::UNVERSIONED;
341         return false;
342 }
343
344
345 string const LyXVC::versionString() const
346 {
347         if (!vcs)
348                 return string();
349         return vcs->versionString();
350 }
351
352
353 bool LyXVC::locking() const
354 {
355         if (!vcs)
356                 return false;
357         return vcs->status() != VCS::NOLOCKING;
358 }
359
360
361 string const LyXVC::getLogFile() const
362 {
363         if (!vcs)
364                 return string();
365
366         FileName const tmpf = FileName::tempName("lyxvclog");
367         if (tmpf.empty()) {
368                 LYXERR(Debug::LYXVC, "Could not generate logfile " << tmpf);
369                 return string();
370         }
371         LYXERR(Debug::LYXVC, "Generating logfile " << tmpf);
372         vcs->getLog(tmpf);
373         return tmpf.absFileName();
374 }
375
376
377 string LyXVC::revisionInfo(RevisionInfo const info) const
378 {
379         if (!vcs)
380                 return string();
381
382         return vcs->revisionInfo(info);
383 }
384
385
386 bool LyXVC::renameEnabled() const
387 {
388         if (!inUse())
389                 return false;
390         return vcs->renameEnabled();
391 }
392
393
394 bool LyXVC::copyEnabled() const
395 {
396         if (!inUse())
397                 return false;
398         return vcs->copyEnabled();
399 }
400
401
402 bool LyXVC::checkOutEnabled() const
403 {
404         return vcs && vcs->checkOutEnabled();
405 }
406
407
408 bool LyXVC::checkInEnabled() const
409 {
410         return vcs && vcs->checkInEnabled();
411 }
412
413
414 bool LyXVC::isCheckInWithConfirmation() const
415 {
416         return vcs && vcs->isCheckInWithConfirmation();
417 }
418
419
420 bool LyXVC::lockingToggleEnabled() const
421 {
422         return vcs && vcs->lockingToggleEnabled();
423 }
424
425
426 bool LyXVC::undoLastEnabled() const
427 {
428         return vcs && vcs->undoLastEnabled();
429 }
430
431
432 bool LyXVC::repoUpdateEnabled() const
433 {
434         return vcs && vcs->repoUpdateEnabled();
435 }
436         
437         
438 bool LyXVC::prepareFileRevision(string const & rev, std::string & f)
439 {
440         return vcs && vcs->prepareFileRevision(rev, f);
441 }
442
443
444 bool LyXVC::prepareFileRevisionEnabled()
445 {
446         return vcs && vcs->prepareFileRevisionEnabled();
447 }
448
449 } // namespace lyx