]> git.lyx.org Git - features.git/blob - src/VCBackend.h
Fix bug with registering files for VC when they are in repo subdirs.
[features.git] / src / VCBackend.h
1 // -*- C++ -*-
2 /**
3  * \file VCBackend.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Lars Gullik Bjønnes
8  * \author Pavel Sanda
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #ifndef VC_BACKEND_H
14 #define VC_BACKEND_H
15
16 #include "support/FileName.h"
17
18 #include <string>
19 #include <vector>
20
21 #include "LyXVC.h"
22
23
24 namespace lyx {
25
26 class Buffer;
27
28 /// A simple version control system interface
29 class VCS {
30 public:
31         /// the status of the managed file
32         enum VCStatus {
33                 UNLOCKED,
34                 LOCKED,
35                 NOLOCKING,
36         };
37
38         VCS(Buffer * b) : vcstatus_(NOLOCKING), owner_(b) {}
39         virtual ~VCS() {}
40
41         /// the name of the vc backend
42         virtual std::string vcname() const = 0;
43         /// register a file for version control
44         virtual void registrer(std::string const & msg) = 0;
45         /// can this operation be processed in the current VCS?
46         virtual bool renameEnabled() = 0;
47         /// rename a file. Return non-empty log on success, empty log on failure.
48         virtual std::string rename(support::FileName const &, std::string const &) = 0;
49         /// can this operation be processed in the current VCS?
50         virtual bool copyEnabled() = 0;
51         /// copy a file. Return non-empty log on success, empty log on failure.
52         virtual std::string copy(support::FileName const &, std::string const &) = 0;
53         /// check in the current revision.
54         /// \p log is non-empty on success and may be empty on failure.
55         virtual LyXVC::CommandResult
56         checkIn(std::string const & msg, std::string & log) = 0;
57         /// can this operation be processed in the current VCS?
58         virtual bool checkInEnabled() = 0;
59         /// should a log message provided for next checkin?
60         virtual bool isCheckInWithConfirmation() = 0;
61         /// check out for editing, returns log
62         virtual std::string checkOut() = 0;
63         /// can this operation be processed in the current VCS?
64         virtual bool checkOutEnabled() = 0;
65         /// synchronize with repository, returns log
66         virtual std::string repoUpdate() = 0;
67         /// can this operation be processed in the current VCS?
68         virtual bool repoUpdateEnabled() = 0;
69         /// toggle locking property of the file
70         virtual std::string lockingToggle() = 0;
71         /// can this operation be processed in the current VCS?
72         virtual bool lockingToggleEnabled() = 0;
73         /// revert current edits
74         virtual bool revert() = 0;
75         /// should a confirmation before revert requested?
76         virtual bool isRevertWithConfirmation() = 0;
77         /**
78          * Merge the current with the previous version
79          * in a reverse patch kind of way, so that the
80          * result is to revert the last changes.
81          */
82         virtual void undoLast() = 0;
83         /// can this operation be processed in the current VCS?
84         virtual bool undoLastEnabled() = 0;
85         /**
86          * getLog - read the revision log into the given file
87          * @param fname file name to read into
88          */
89         virtual void getLog(support::FileName const &) = 0;
90         /// return the current version description
91         virtual std::string const versionString() const = 0;
92         /// return the owning buffer
93         Buffer * owner() const { return owner_; }
94         /// return the lock status of this file
95         VCStatus status() const { return vcstatus_; }
96         /// do we need special handling for read-only toggling?
97         /// (also used for check-out operation)
98         virtual bool toggleReadOnlyEnabled() = 0;
99         /// Return revision info specified by the argument.
100         virtual std::string revisionInfo(LyXVC::RevisionInfo const info) = 0;
101         /// can this operation be processed in the current VCS?
102         virtual bool prepareFileRevision(std::string const & rev, std::string & f) = 0;
103         /// can this operation be processed in the current VCS?
104         virtual bool prepareFileRevisionEnabled() = 0;
105
106         /// Check the directory given in start and all parent directories
107         /// for the existence of some other file
108         /// \param start : where we start looking (we will strip the filename if given
109         ///                     and just use the directory
110         /// \param file : the directory or file for which to look
111         ///                     Note that this can be e.g. ".git/index", so we will look for the .git
112         ///                     directory and also for an index file in it.
113         /// Returns a FileName object for the found file or else an empty FileName
114         static support::FileName checkParentDirs(support::FileName const & start, std::string const & file);
115
116 protected:
117         /// parse information from the version file
118         virtual void scanMaster() = 0;
119
120         /// Prepare a version identifier suitable for RCS and CVS.
121         /// If needed converts last or relative number to the absolute revision.
122         bool makeRCSRevision(std::string const &version, std::string &revis) const;
123
124         /// GUI container for doVCCommandCall
125         int doVCCommand(std::string const & cmd, support::FileName const & path, bool reportError = true);
126         /**
127          * doVCCommandCall - call out to the version control utility
128          * @param cmd the command to execute
129          * @param path the path from which to execute
130          * @return exit status
131          */
132         static int doVCCommandCall(std::string const & cmd, support::FileName const & path);
133
134         /**
135          * The master VC file. For RCS this is *,v or RCS/ *,v. master should
136          * have full path.
137          */
138         support::FileName master_;
139
140         /// The status of the VC controlled file.
141         VCStatus vcstatus_;
142
143         /// The buffer using this VC
144         Buffer * const owner_;
145 };
146
147
148 ///
149 class RCS : public VCS {
150 public:
151
152         explicit
153         RCS(support::FileName const & m, Buffer * b);
154
155         /// return the revision file for the given file, if found
156         static support::FileName const findFile(support::FileName const & file);
157
158         /// get file from repo, the caller must ensure that it does not exist locally
159         static bool retrieve(support::FileName const & file);
160
161         std::string vcname() const override { return "RCS"; };
162
163         void registrer(std::string const & msg) override;
164
165         bool renameEnabled() override;
166
167         std::string rename(support::FileName const &, std::string const &) override;
168
169         bool copyEnabled() override;
170
171         std::string copy(support::FileName const &, std::string const &) override;
172
173         LyXVC::CommandResult
174         checkIn(std::string const & msg, std::string & log) override;
175
176         bool checkInEnabled() override;
177
178         bool isCheckInWithConfirmation() override;
179
180         std::string checkOut() override;
181
182         bool checkOutEnabled() override;
183
184         std::string repoUpdate() override;
185
186         bool repoUpdateEnabled() override;
187
188         std::string lockingToggle() override;
189
190         bool lockingToggleEnabled() override;
191
192         bool revert() override;
193
194         bool isRevertWithConfirmation() override;
195
196         void undoLast() override;
197
198         bool undoLastEnabled() override;
199
200         void getLog(support::FileName const &) override;
201
202         std::string const versionString() const override {
203                 return "RCS: " + version_;
204         }
205
206         bool toggleReadOnlyEnabled() override;
207
208         std::string revisionInfo(LyXVC::RevisionInfo const info) override;
209
210         bool prepareFileRevision(std::string const & rev, std::string & f) override;
211
212         bool prepareFileRevisionEnabled() override;
213
214 protected:
215         void scanMaster() override;
216 private:
217         bool getRevisionInfo();
218         /**
219          * The version of the VC file. I am not sure if this can be a
220          * string or if it must be a float/int.
221          */
222         std::string version_;
223         /// The user currently keeping the lock on the VC file (or "Unlocked").
224         std::string locker_;
225         /// Cache for revision info.
226         std::string rev_date_cache_;
227         ///
228         std::string rev_time_cache_;
229         ///
230         std::string rev_author_cache_;
231 };
232
233
234 ///
235 class CVS : public VCS {
236 public:
237         ///
238         explicit
239         CVS(support::FileName const & m, Buffer * b);
240
241         /// return the revision file for the given file, if found
242         static support::FileName const findFile(support::FileName const & file);
243
244         /// get file from repo, the caller must ensure that it does not exist locally
245         static bool retrieve(support::FileName const & file);
246
247         std::string vcname() const override { return "CVS"; };
248
249         void registrer(std::string const & msg) override;
250
251         bool renameEnabled() override;
252
253         std::string rename(support::FileName const &, std::string const &) override;
254
255         bool copyEnabled() override;
256
257         std::string copy(support::FileName const &, std::string const &) override;
258
259         LyXVC::CommandResult
260         checkIn(std::string const & msg, std::string & log) override;
261
262         bool checkInEnabled() override;
263
264         bool isCheckInWithConfirmation() override;
265
266         std::string checkOut() override;
267
268         bool checkOutEnabled() override;
269
270         std::string repoUpdate() override;
271
272         bool repoUpdateEnabled() override;
273
274         std::string lockingToggle() override;
275
276         bool lockingToggleEnabled() override;
277
278         bool isRevertWithConfirmation() override;
279
280         bool revert() override;
281
282         void undoLast() override;
283
284         bool undoLastEnabled() override;
285
286         void getLog(support::FileName const &) override;
287
288         /// Check for messages in cvs output.
289         /// Returns conflict line.
290         std::string scanLogFile(support::FileName const & f, std::string & status);
291
292         std::string const versionString() const override {
293                 return "CVS: " + version_;
294         }
295
296         bool toggleReadOnlyEnabled() override;
297
298         std::string revisionInfo(LyXVC::RevisionInfo const info) override;
299
300         bool prepareFileRevision(std::string const & rev, std::string & f) override;
301
302         bool prepareFileRevisionEnabled() override;
303
304 protected:
305         void scanMaster() override;
306         /// the mode of operation for some VC commands
307         enum OperationMode {
308                 Directory = 0,
309                 File = 1
310         };
311         /// possible status values of file
312         enum CvsStatus {
313                 UpToDate = 0,
314                 LocallyModified = 1,
315                 LocallyAdded = 2,
316                 NeedsMerge = 3,
317                 NeedsCheckout = 4,
318                 NoCvsFile = 5,
319                 StatusError = 6
320         };
321
322 private:
323         // revision number from scanMaster
324         std::string version_;
325
326         /**
327          * doVCCommandWithOutput
328          * - call out to the version control utility
329          * - it is able to collect output in a file
330          * @param cmd the command to execute
331          * @param path the path from which to execute
332          * @param output the path where to store output
333          * @param reportError display of low level error message dialog
334          * @return exit status
335          */
336         int doVCCommandWithOutput(std::string const & cmd,
337                         support::FileName const & path,
338                         support::FileName const & output,
339                         bool reportError = true);
340         static int doVCCommandCallWithOutput(std::string const & cmd,
341                         support::FileName const & path,
342                         support::FileName const & output);
343
344         /// return the quoted pathname if Directory or filename if File
345         std::string const getTarget(OperationMode opmode) const;
346         /// collect the diff of file or directory against repository
347         /// result is placed in temporary file
348         void getDiff(OperationMode opmode, support::FileName const & tmpf);
349         /// make the file ready for editing:
350         /// save a copy in CVS/Base and change file permissions to rw if needed
351         int edit();
352         /// revert the edit operation
353         int unedit();
354         /// retrieve repository changes into working copy
355         int update(OperationMode opmode, support::FileName const & tmpf);
356         /// check readonly state for file
357         /// assume true when file is writable
358         bool isLocked() const;
359         /// query and parse the cvs status of file
360         CvsStatus getStatus();
361         /// convert enum to string
362         docstring toString(CvsStatus status) const;
363
364         /// cache the info values of current file revision
365         /// author, date and time of commit
366         std::string rev_author_cache_;
367         std::string rev_date_cache_;
368         std::string rev_time_cache_;
369         /// fills the cache values, returns true if successfull.
370         void getRevisionInfo();
371         bool have_rev_info_;
372 };
373
374
375 ///
376 class SVN : public VCS {
377 public:
378         ///
379         explicit
380         SVN(support::FileName const & m, Buffer * b);
381
382         /// return the revision file for the given file, if found
383         static support::FileName const findFile(support::FileName const & file);
384
385         /// get file from repo, the caller must ensure that it does not exist locally
386         static bool retrieve(support::FileName const & file);
387
388         std::string vcname() const override { return "SVN"; };
389
390         void registrer(std::string const & msg) override;
391
392         bool renameEnabled() override;
393
394         std::string rename(support::FileName const &, std::string const &) override;
395
396         bool copyEnabled() override;
397
398         std::string copy(support::FileName const &, std::string const &) override;
399
400         LyXVC::CommandResult
401         checkIn(std::string const & msg, std::string & log) override;
402
403         bool checkInEnabled() override;
404
405         bool isCheckInWithConfirmation() override;
406
407         std::string checkOut() override;
408
409         bool checkOutEnabled() override;
410
411         std::string repoUpdate() override;
412
413         bool repoUpdateEnabled() override;
414
415         std::string lockingToggle() override;
416
417         bool lockingToggleEnabled() override;
418
419         bool revert() override;
420
421         bool isRevertWithConfirmation() override;
422
423         void undoLast() override;
424
425         bool undoLastEnabled() override;
426
427         void getLog(support::FileName const &) override;
428
429         std::string const versionString() const override {
430                 return "SVN: " + rev_file_cache_;
431         }
432
433         bool toggleReadOnlyEnabled() override;
434
435         std::string revisionInfo(LyXVC::RevisionInfo const info) override;
436
437         bool prepareFileRevision(std::string const & rev, std::string & f) override;
438
439         bool prepareFileRevisionEnabled() override;
440
441 protected:
442         void scanMaster() override;
443         /// Check for messages in svn output. Returns error.
444         std::string scanLogFile(support::FileName const & f, std::string & status);
445         /// checks locking policy and setup locked_mode_
446         bool checkLockMode();
447         /// is the loaded file locked?
448         bool isLocked() const;
449         /// acquire/release write lock for the current file
450         bool fileLock(bool lock, support::FileName const & tmpf, std::string & status);
451         /// Check in files \p f with log \p msg
452         LyXVC::CommandResult checkIn(std::vector<support::FileName> const & f,
453                                      std::string const & msg, std::string & log);
454
455 private:
456         /// is the loaded file under locking policy?
457         bool locked_mode_;
458         /**
459          * Real code for obtaining file revision info. Fills all file-related caches
460          * and returns true if successfull.
461          * "?" is stored in rev_file_cache_ as a signal if request for obtaining info
462          * was already unsuccessful.
463          */
464         bool getFileRevisionInfo();
465         /// cache for file revision number, "?" if already unsuccessful, isNumber==true
466         std::string rev_file_cache_;
467         /// cache for author of last commit
468         std::string rev_author_cache_;
469         /// cache for date of last commit
470         std::string rev_date_cache_;
471         /// cache for time of last commit
472         std::string rev_time_cache_;
473         /// fills rev_tree_cache_, returns true if successfull.
474         bool getTreeRevisionInfo();
475         /// cache for tree revision number, "?" if already unsuccessful
476         std::string rev_tree_cache_;
477 };
478
479
480 /**
481  * Very basic git support:
482  * Remote repos are completely ignored, only the local tree is considered.
483  * How push and pull could be integrated with the LyX VCS interface needs
484  * to be discussed.
485  */
486 class GIT : public VCS {
487 public:
488         ///
489         explicit
490         GIT(support::FileName const & m, Buffer * b);
491
492         /// return the revision file for the given file, if found
493         static support::FileName const findFile(support::FileName const & file);
494
495         /// get file from repo, the caller must ensure that it does not exist locally
496         static bool retrieve(support::FileName const & file);
497
498         std::string vcname() const override { return "GIT"; };
499
500         void registrer(std::string const & msg) override;
501
502         bool renameEnabled() override;
503
504         std::string rename(support::FileName const &, std::string const &) override;
505
506         bool copyEnabled() override;
507
508         std::string copy(support::FileName const &, std::string const &) override;
509
510         LyXVC::CommandResult
511         checkIn(std::string const & msg, std::string & log) override;
512
513         bool checkInEnabled() override;
514
515         bool isCheckInWithConfirmation() override;
516
517         std::string checkOut() override;
518
519         bool checkOutEnabled() override;
520
521         std::string repoUpdate() override;
522
523         bool repoUpdateEnabled() override;
524
525         std::string lockingToggle() override;
526
527         bool lockingToggleEnabled() override;
528
529         bool revert() override;
530
531         bool isRevertWithConfirmation() override;
532
533         void undoLast() override;
534
535         bool undoLastEnabled() override;
536
537         void getLog(support::FileName const &) override;
538
539         std::string const versionString() const override {
540                 return "GIT: ?";
541         }
542
543         bool toggleReadOnlyEnabled() override;
544
545         std::string revisionInfo(LyXVC::RevisionInfo const info) override;
546
547         bool prepareFileRevision(std::string const & rev, std::string & f) override;
548
549         bool prepareFileRevisionEnabled() override;
550
551 protected:
552         void scanMaster() override;
553         /// Check for messages in svn output. Returns error.
554         std::string scanLogFile(support::FileName const & f, std::string & status);
555         /// Check in files \p f with log \p msg
556         LyXVC::CommandResult checkIn(std::vector<support::FileName> const & f,
557                                      std::string const & msg, std::string & log);
558
559 private:
560         /**
561          * Real code for obtaining file revision info. Fills all file-related caches
562          * and returns true if successfull.
563          * "?" is stored in rev_file_cache_ as a signal if request for obtaining info
564          * was already unsuccessful.
565          */
566         bool getFileRevisionInfo();
567         /// cache for file revision number, "?" if already unsuccessful, isNumber==true
568         std::string rev_file_cache_;
569         /// cache for abbreviated file revision number, "?" if already unsuccessful, isNumber==true
570         std::string rev_file_abbrev_cache_;
571         /// cache for author of last commit
572         std::string rev_author_cache_;
573         /// cache for date of last commit
574         std::string rev_date_cache_;
575         /// cache for time of last commit
576         std::string rev_time_cache_;
577         /// fills rev_tree_cache_, returns true if successfull.
578         bool getTreeRevisionInfo();
579         /// cache for tree revision number, "?" if already unsuccessful
580         std::string rev_tree_cache_;
581 };
582
583 } // namespace lyx
584
585 #endif // VCBACKEND_H