]> git.lyx.org Git - features.git/blob - src/VCBackend.h
Implement VCS copy and rename
[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                 /// This file is not in version control, but it could be aded
37                 /// (because the path is under version control)
38                 UNVERSIONED,
39         };
40
41         VCS(Buffer * b) : owner_(b) {}
42         virtual ~VCS() {}
43
44         /// register a file for version control
45         virtual void registrer(std::string const & msg) = 0;
46         /// can this operation be processed in the current VCS?
47         virtual bool renameEnabled() = 0;
48         /// rename a file. Return non-empty log on success, empty log on failure.
49         virtual std::string rename(support::FileName const &, std::string const &) = 0;
50         /// copy a file. Return non-empty log on success, empty log on failure.
51         virtual std::string copy(support::FileName const &, std::string const &) = 0;
52         /// check in the current revision.
53         /// \p log is non-empty on success and may be empty on failure.
54         virtual LyXVC::CommandResult
55         checkIn(std::string const & msg, std::string & log) = 0;
56         /// can this operation be processed in the current VCS?
57         virtual bool checkInEnabled() = 0;
58         /// should a log message provided for next checkin?
59         virtual bool isCheckInWithConfirmation() = 0;
60         /// check out for editing, returns log
61         virtual std::string checkOut() = 0;
62         /// can this operation be processed in the current VCS?
63         virtual bool checkOutEnabled() = 0;
64         /// synchronize with repository, returns log
65         virtual std::string repoUpdate() = 0;
66         /// can this operation be processed in the current VCS?
67         virtual bool repoUpdateEnabled() = 0;
68         /// toggle locking property of the file
69         virtual std::string lockingToggle() = 0;
70         /// can this operation be processed in the current VCS?
71         virtual bool lockingToggleEnabled() = 0;
72         /// revert current edits
73         virtual bool revert() = 0;
74         /// should a confirmation before revert requested?
75         virtual bool isRevertWithConfirmation() = 0;
76         /**
77          * Merge the current with the previous version
78          * in a reverse patch kind of way, so that the
79          * result is to revert the last changes.
80          */
81         virtual void undoLast() = 0;
82         /// can this operation be processed in the current VCS?
83         virtual bool undoLastEnabled() = 0;
84         /**
85          * getLog - read the revision log into the given file
86          * @param fname file name to read into
87          */
88         virtual void getLog(support::FileName const &) = 0;
89         /// return the current version description
90         virtual std::string const versionString() const = 0;
91         /// return the owning buffer
92         Buffer * owner() const { return owner_; }
93         /// return the lock status of this file
94         VCStatus status() const { return vcstatus; }
95         /// do we need special handling for read-only toggling?
96         /// (also used for check-out operation)
97         virtual bool toggleReadOnlyEnabled() = 0;
98         /// Return revision info specified by the argument.
99         virtual std::string revisionInfo(LyXVC::RevisionInfo const info) = 0;
100         /// can this operation be processed in the current VCS?
101         virtual bool prepareFileRevision(std::string const & rev, std::string & f) = 0;
102         /// can this operation be processed in the current VCS?
103         virtual bool prepareFileRevisionEnabled() = 0;
104
105         /// Check the directory of file and all parent directories
106         /// for the existence of the given pathname
107         static bool checkparentdirs(support::FileName const & file, std::string const & pathname);
108         
109 protected:
110         /// parse information from the version file
111         virtual void scanMaster() = 0;
112
113         /// Prepare a version identifier suitable for RCS and CVS.
114         /// If needed converts last or relative number to the absolute revision.
115         bool makeRCSRevision(std::string const &version, std::string &revis) const;
116         
117         /// GUI container for doVCCommandCall
118         int doVCCommand(std::string const & cmd, support::FileName const & path, bool reportError = true);
119         /**
120          * doVCCommandCall - call out to the version control utility
121          * @param cmd the command to execute
122          * @param path the path from which to execute
123          * @return exit status
124          */
125         static int doVCCommandCall(std::string const & cmd, support::FileName const & path);
126
127         /**
128          * The master VC file. For RCS this is *,v or RCS/ *,v. master should
129          * have full path.
130          */
131         support::FileName master_;
132
133         /// The status of the VC controlled file.
134         VCStatus vcstatus;
135
136         /// The buffer using this VC
137         Buffer * const owner_;
138 };
139
140
141 ///
142 class RCS : public VCS {
143 public:
144
145         explicit
146         RCS(support::FileName const & m, Buffer * b);
147
148         /// return the revision file for the given file, if found
149         static support::FileName const findFile(support::FileName const & file);
150
151         static bool retrieve(support::FileName const & file);
152
153         virtual void registrer(std::string const & msg);
154
155         virtual bool renameEnabled();
156
157         virtual std::string rename(support::FileName const &, std::string const &);
158
159         virtual std::string copy(support::FileName const &, std::string const &);
160
161         virtual LyXVC::CommandResult
162         checkIn(std::string const & msg, std::string & log);
163
164         virtual bool checkInEnabled();
165
166         virtual bool isCheckInWithConfirmation();
167
168         virtual std::string checkOut();
169
170         virtual bool checkOutEnabled();
171
172         virtual std::string repoUpdate();
173
174         virtual bool repoUpdateEnabled();
175
176         virtual std::string lockingToggle();
177
178         virtual bool lockingToggleEnabled();
179
180         virtual bool revert();
181
182         virtual bool isRevertWithConfirmation();
183
184         virtual void undoLast();
185
186         virtual bool undoLastEnabled();
187
188         virtual void getLog(support::FileName const &);
189
190         virtual std::string const versionString() const {
191                 return "RCS: " + version_;
192         }
193
194         virtual bool toggleReadOnlyEnabled();
195
196         virtual std::string revisionInfo(LyXVC::RevisionInfo const info);
197
198         virtual bool prepareFileRevision(std::string const & rev, std::string & f);
199
200         virtual bool prepareFileRevisionEnabled();
201
202 protected:
203         virtual void scanMaster();
204 private:
205         bool getRevisionInfo();
206         /**
207          * The version of the VC file. I am not sure if this can be a
208          * string or if it must be a float/int.
209          */
210         std::string version_;
211         /// The user currently keeping the lock on the VC file (or "Unlocked").
212         std::string locker_;
213         /// Cache for revision info.
214         std::string rev_date_cache_;
215         ///
216         std::string rev_time_cache_;
217         ///
218         std::string rev_author_cache_;
219 };
220
221
222 ///
223 class CVS : public VCS {
224 public:
225         ///
226         explicit
227         CVS(support::FileName const & m, Buffer * b);
228
229         /// return the revision file for the given file, if found
230         static support::FileName const findFile(support::FileName const & file);
231
232         static bool retrieve(support::FileName const & file);
233
234         virtual void registrer(std::string const & msg);
235
236         virtual bool renameEnabled();
237
238         virtual std::string rename(support::FileName const &, std::string const &);
239
240         virtual std::string copy(support::FileName const &, std::string const &);
241
242         virtual LyXVC::CommandResult
243         checkIn(std::string const & msg, std::string & log);
244
245         virtual bool checkInEnabled();
246
247         virtual bool isCheckInWithConfirmation();
248
249         virtual std::string checkOut();
250
251         virtual bool checkOutEnabled();
252
253         virtual std::string repoUpdate();
254
255         virtual bool repoUpdateEnabled();
256
257         virtual std::string lockingToggle();
258
259         virtual bool lockingToggleEnabled();
260
261         virtual bool isRevertWithConfirmation();
262
263         virtual bool revert();
264
265         virtual void undoLast();
266
267         virtual bool undoLastEnabled();
268
269         virtual void getLog(support::FileName const &);
270
271         /// Check for messages in cvs output. 
272         /// Returns conflict line.
273         std::string scanLogFile(support::FileName const & f, std::string & status);
274
275         virtual std::string const versionString() const {
276                 return "CVS: " + version_;
277         }
278
279         virtual bool toggleReadOnlyEnabled();
280
281         virtual std::string revisionInfo(LyXVC::RevisionInfo const info);
282
283         virtual bool prepareFileRevision(std::string const & rev, std::string & f);
284
285         virtual bool prepareFileRevisionEnabled();
286
287 protected:
288         virtual void scanMaster();
289         /// the mode of operation for some VC commands
290         enum OperationMode {
291                 Directory = 0,
292                 File = 1
293         };
294         /// possible status values of file
295         enum CvsStatus {
296                 UpToDate = 0,
297                 LocallyModified = 1,
298                 LocallyAdded = 2,
299                 NeedsMerge = 3,
300                 NeedsCheckout = 4,
301                 NoCvsFile = 5,
302                 StatusError = 6
303         };
304
305 private:
306         // revision number from scanMaster
307         std::string version_;
308
309         /**
310          * doVCCommandWithOutput
311          * - call out to the version control utility
312          * - it is able to collect output in a file
313          * @param cmd the command to execute
314          * @param path the path from which to execute
315          * @param output the path where to store output
316          * @param reportError display of low level error message dialog
317          * @return exit status
318          */
319         int doVCCommandWithOutput(std::string const & cmd,
320                         support::FileName const & path,
321                         support::FileName const & output,
322                         bool reportError = true);
323         static int doVCCommandCallWithOutput(std::string const & cmd,
324                         support::FileName const & path,
325                         support::FileName const & output);
326                                                 
327         /// return the quoted pathname if Directory or filename if File
328         virtual std::string const getTarget(OperationMode opmode) const;
329         /// collect the diff of file or directory against repository
330         /// result is placed in temporary file
331         void getDiff(OperationMode opmode, support::FileName const & tmpf);
332         /// make the file ready for editing:
333         /// save a copy in CVS/Base and change file permissions to rw if needed
334         virtual int edit();
335         /// revert the edit operation
336         virtual int unedit();
337         /// retrieve repository changes into working copy
338         virtual int update(OperationMode opmode, support::FileName const & tmpf);
339         /// check readonly state for file
340         /// assume true when file is writable
341         virtual bool isLocked() const;
342         /// query and parse the cvs status of file
343         virtual CvsStatus getStatus();
344         /// convert enum to string
345         virtual docstring toString(CvsStatus status) const;
346
347         /// cache the info values of current file revision
348         /// author, date and time of commit
349         std::string rev_author_cache_;
350         std::string rev_date_cache_;
351         std::string rev_time_cache_;
352         /// fills the cache values, returns true if successfull.
353         void getRevisionInfo();
354         bool have_rev_info_;
355 };
356
357
358 ///
359 class SVN : public VCS {
360 public:
361         ///
362         explicit
363         SVN(support::FileName const & m, Buffer * b);
364
365         /// return the revision file for the given file, if found
366         static support::FileName const findFile(support::FileName const & file);
367
368         static bool retrieve(support::FileName const & file);
369
370         virtual void registrer(std::string const & msg);
371
372         virtual bool renameEnabled();
373
374         virtual std::string rename(support::FileName const &, std::string const &);
375
376         virtual std::string copy(support::FileName const &, std::string const &);
377
378         virtual LyXVC::CommandResult
379         checkIn(std::string const & msg, std::string & log);
380
381         virtual bool checkInEnabled();
382
383         virtual bool isCheckInWithConfirmation();
384
385         virtual std::string checkOut();
386
387         virtual bool checkOutEnabled();
388
389         virtual std::string repoUpdate();
390
391         virtual bool repoUpdateEnabled();
392
393         virtual std::string lockingToggle();
394
395         virtual bool lockingToggleEnabled();
396
397         virtual bool revert();
398
399         virtual bool isRevertWithConfirmation();
400
401         virtual void undoLast();
402
403         virtual bool undoLastEnabled();
404
405         virtual void getLog(support::FileName const &);
406
407         virtual std::string const versionString() const {
408                 return "SVN: " + rev_file_cache_;
409         }
410
411         virtual bool toggleReadOnlyEnabled();
412
413         virtual std::string revisionInfo(LyXVC::RevisionInfo const info);
414
415         virtual bool prepareFileRevision(std::string const & rev, std::string & f);
416
417         virtual bool prepareFileRevisionEnabled();
418
419 protected:
420         virtual void scanMaster();
421         /// Check for messages in svn output. Returns error.
422         std::string scanLogFile(support::FileName const & f, std::string & status);
423         /// checks locking policy and setup locked_mode_
424         bool checkLockMode();
425         /// is the loaded file locked?
426         bool isLocked() const;
427         /// acquire/release write lock for the current file
428         bool fileLock(bool lock, support::FileName const & tmpf, std::string & status);
429         /// Check in files \p f with log \p msg
430         LyXVC::CommandResult checkIn(std::vector<support::FileName> const & f,
431                                      std::string const & msg, std::string & log);
432
433 private:
434         /// is the loaded file under locking policy?
435         bool locked_mode_;
436         /**
437          * Real code for obtaining file revision info. Fills all file-related caches
438          * and returns true if successfull.
439          * "?" is stored in rev_file_cache_ as a signal if request for obtaining info
440          * was already unsuccessful.
441          */
442         bool getFileRevisionInfo();
443         /// cache for file revision number, "?" if already unsuccessful, isNumber==true
444         std::string rev_file_cache_;
445         /// cache for author of last commit
446         std::string rev_author_cache_;
447         /// cache for date of last commit
448         std::string rev_date_cache_;
449         /// cache for time of last commit
450         std::string rev_time_cache_;
451         /// fills rev_tree_cache_, returns true if successfull.
452         bool getTreeRevisionInfo();
453         /// cache for tree revision number, "?" if already unsuccessful
454         std::string rev_tree_cache_;
455 };
456
457 } // namespace lyx
458
459 #endif // VCBACKEND_H