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