]> git.lyx.org Git - lyx.git/blob - src/vc-backend.C
Applied Angus patch to compile on DEC C++ and to avoid name clashes
[lyx.git] / src / vc-backend.C
1 #include <config.h>
2
3 #ifdef __GNUG__
4 #pragma implementation
5 #endif
6
7 #include <fstream>
8
9 #include "vc-backend.h"
10 #include "debug.h"
11 #include "support/FileInfo.h"
12 #include "support/LRegex.h"
13 #include "support/LSubstring.h"
14 #include "support/path.h"
15 #include "support/filetools.h"
16 #include "buffer.h"
17 #include "LyXView.h"
18 #include "lyxfunc.h"
19
20 using std::endl;
21 using std::ifstream;
22 using std::getline;
23
24 int VCS::doVCCommand(string const & cmd, string const & path)
25 {
26         lyxerr[Debug::LYXVC] << "doVCCommand: " << cmd << endl;
27         Systemcalls one;
28         Path p(path);
29         int const ret = one.startscript(Systemcalls::System, cmd);
30         return ret;
31 }
32
33
34 RCS::RCS(string const & m)
35 {
36         master_ = m;
37         scanMaster();
38 }
39
40
41 string const RCS::find_file(string const & file)
42 {
43         string tmp(file);
44         // Check if *,v exists.
45         tmp += ",v";
46         FileInfo f;
47         lyxerr[Debug::LYXVC] << "Checking if file is under rcs: "
48                              << tmp << endl;
49         if (f.newFile(tmp).readable()) {
50                 lyxerr[Debug::LYXVC] << "Yes " << file
51                                      << " is under rcs." << endl;
52                 return tmp;
53         } else {
54                 // Check if RCS/*,v exists.
55                 tmp = AddName(AddPath(OnlyPath(file), "RCS"), file);
56                 tmp += ",v";
57                 lyxerr[Debug::LYXVC] << "Checking if file is under rcs: "
58                                      << tmp << endl;
59                 if (f.newFile(tmp).readable()) {
60                         lyxerr[Debug::LYXVC] << "Yes " << file
61                                              << " it is under rcs."<< endl;
62                         return tmp;
63                 }
64         }
65         return string();
66 }
67
68
69 void RCS::retrive(string const & file)
70 {
71         lyxerr[Debug::LYXVC] << "LyXVC::RCS: retrive.\n\t" << file << endl;
72         VCS::doVCCommand("co -q -r \""
73                          + file + "\"",
74                          string());
75 }
76
77
78 void RCS::scanMaster()
79 {
80         lyxerr[Debug::LYXVC] << "LyXVC::RCS: scanMaster." << endl;
81
82         ifstream ifs(master_.c_str());
83
84         string token;
85         bool read_enough = false;
86
87         while (!read_enough && ifs >> token) {
88                 lyxerr[Debug::LYXVC]
89                         << "LyXVC::scanMaster: current lex text: `"
90                         << token << "'" << endl;
91
92                 if (token.empty())
93                         continue;
94                 else if (token == "head") {
95                         // get version here
96                         string tmv;
97                         ifs >> tmv;
98                         tmv = strip(tmv, ';');
99                         version_ = tmv;
100                         lyxerr[Debug::LYXVC] << "LyXVC: version found to be "
101                                              << tmv << endl;
102                 } else if (contains(token, "access")
103                            || contains(token, "symbols")
104                            || contains(token, "strict")) {
105                         // nothing
106                 } else if (contains(token, "locks")) {
107                         // get locker here
108                         if (contains(token, ";")) {
109                                 locker_ = "Unlocked";
110                                 vcstatus = UNLOCKED;
111                                 continue;
112                         }
113                         string tmpt, s1, s2;
114                         do {
115                                 ifs >> tmpt;
116                                 s1 = strip(tmpt, ';');
117                                 // tmp is now in the format <user>:<version>
118                                 s1 = split(s1, s2, ':');
119                                 // s2 is user, and s1 is version
120                                 if (s1 == version_) {
121                                         locker_ = s2;
122                                         vcstatus = LOCKED;
123                                         break;
124                                 }
125                         } while (!contains(tmpt, ";"));
126                         
127                 } else if (token == "comment") {
128                         // we don't need to read any further than this.
129                         read_enough = true;
130                 } else {
131                         // unexpected
132                         lyxerr[Debug::LYXVC]
133                                 << "LyXVC::scanMaster(): unexpected token"
134                                 << endl;
135                 }
136         }
137         version_ = "RCS: " + version_;
138 }
139
140
141 void RCS::registrer(string const & msg)
142 {
143         string cmd = "ci -q -u -i -t-\"";
144         cmd += msg;
145         cmd += "\" \"";
146         cmd += OnlyFilename(owner_->fileName());
147         cmd += "\"";
148         doVCCommand(cmd, owner_->filepath);
149         owner_->getUser()->owner()->getLyXFunc()->Dispatch("buffer-reload");
150 }
151
152
153 void RCS::checkIn(string const & msg)
154 {
155         doVCCommand("ci -q -u -m\"" + msg + "\" \""
156                     + OnlyFilename(owner_->fileName()) + "\"", owner_->filepath);
157         owner_->getUser()->owner()->getLyXFunc()->Dispatch("buffer-reload");
158 }
159
160
161 void RCS::checkOut()
162 {
163         owner_->markLyxClean();
164         doVCCommand("co -q -l \""
165                     + OnlyFilename(owner_->fileName()) + "\"", owner_->filepath);
166         owner_->getUser()->owner()->getLyXFunc()->Dispatch("buffer-reload");
167 }
168
169
170 void RCS::revert()
171 {
172         doVCCommand("co -f -u" + version() + " \""
173                     + OnlyFilename(owner_->fileName()) + "\"", owner_->filepath);
174         // We ignore changes and just reload!
175         owner_->markLyxClean();
176         owner_->getUser()->owner()
177                 ->getLyXFunc()->Dispatch("buffer-reload");
178 }
179
180
181 void RCS::undoLast()
182 {
183         lyxerr[Debug::LYXVC] << "LyXVC: undoLast" << endl;
184         doVCCommand("rcs -o" + version() + " \""
185                     + OnlyFilename(owner_->fileName()) + "\"",
186                     owner_->filepath);
187 }
188
189
190 void RCS::getLog(string const & tmpf)
191 {
192         doVCCommand("rlog \""
193                     + OnlyFilename(owner_->fileName()) + "\" > " + tmpf, owner_->filepath);
194 }
195
196
197 CVS::CVS(string const & m, string const & f)
198 {
199         master_ = m;
200         file_ = f;
201         scanMaster();
202 }
203
204
205 string const CVS::find_file(string const & file)
206 {
207         // First we look for the CVS/Entries in the same dir
208         // where we have file.
209         string const dir = OnlyPath(file) + "/CVS/Entries";
210         string const tmpf = "/" + OnlyFilename(file) + "/";
211         lyxerr[Debug::LYXVC] << "LyXVC: checking in `" << dir
212                              << "' for `" << tmpf << "'" << endl;
213         FileInfo const f(dir);
214         if (f.readable()) {
215                 // Ok we are at least in a CVS dir. Parse the CVS/Entries
216                 // and see if we can find this file. We do a fast and
217                 // dirty parse here.
218                 ifstream ifs(dir.c_str());
219                 string line;
220                 while (getline(ifs, line)) {
221                         lyxerr[Debug::LYXVC] << "\tEntries: " << line << endl;
222                         if (contains(line, tmpf)) return dir;
223                 }
224         }
225         return string();
226 }
227
228
229 void CVS::scanMaster()
230 {
231         lyxerr[Debug::LYXVC] << "LyXVC::CVS: scanMaster. \n     Checking: "
232                              << master_ << endl;
233         // Ok now we do the real scan...
234         ifstream ifs(master_.c_str());
235         string tmpf = "/" + OnlyFilename(file_) + "/";
236         lyxerr[Debug::LYXVC] << "\tlooking for `" << tmpf << "'" << endl;
237         string line;
238         LRegex reg("/(.*)/(.*)/(.*)/(.*)/(.*)");
239         while(getline(ifs, line)) {
240                 lyxerr[Debug::LYXVC] << "\t  line: " << line << endl;
241                 if (contains(line, tmpf)) {
242                         // Ok extract the fields.
243                         LRegex::SubMatches const & sm = reg.exec(line);
244                         //sm[0]; // whole matched string
245                         //sm[1]; // filename
246                         version_ = "CVS: ";
247                         version_ += LSubstring(line, sm[2].first,
248                                               sm[2].second);
249                         string file_date = LSubstring(line, sm[3].first,
250                                                       sm[3].second);
251                         //sm[4]; // options
252                         //sm[5]; // tag or tagdate
253                         FileInfo fi(file_);
254                         time_t mod = fi.getModificationTime();
255                         string mod_date = strip(asctime(gmtime(&mod)), '\n');
256                         lyxerr[Debug::LYXVC]
257                                 <<  "Date in Entries: `" << file_date
258                                 << "'\nModification date of file: `"
259                                 << mod_date << "'" << endl;
260                         if (file_date == mod_date) {
261                                 locker_ = "Unlocked";
262                                 vcstatus = UNLOCKED;
263                         } else {
264                                 // Here we should also to some more checking
265                                 // to see if there are conflicts or not.
266                                 locker_ = "Locked";
267                                 vcstatus = LOCKED;
268                         }
269                         break;
270                 }
271         }
272 }
273
274
275 void CVS::registrer(string const & msg)
276 {
277         doVCCommand("cvs -q add -m \"" + msg + "\" \""
278                     + OnlyFilename(owner_->fileName()) + "\"", owner_->filepath);
279         owner_->getUser()->owner()->getLyXFunc()->Dispatch("buffer-reload");
280 }
281
282
283 void CVS::checkIn(string const & msg)
284 {
285         doVCCommand("cvs -q commit -m \"" + msg + "\" \""
286                     + OnlyFilename(owner_->fileName()) + "\"",
287                     owner_->filepath);
288         owner_->getUser()->owner()->getLyXFunc()->Dispatch("buffer-reload");
289 }
290
291
292 void CVS::checkOut()
293 {
294         // cvs update or perhaps for cvs this should be a noop
295         lyxerr << "Sorry not implemented." << endl;
296 }
297
298
299 void CVS::revert()
300 {
301         // Reverts to the version in CVS repository and
302         // gets the updated version from the repository.
303         string const fil = OnlyFilename(owner_->fileName());
304         
305         doVCCommand("rm -f \"" + fil + "\"; cvs update \"" + fil + "\"",
306                     owner_->filepath);
307         owner_->markLyxClean();
308         owner_->getUser()->owner()
309                 ->getLyXFunc()->Dispatch("buffer-reload");
310 }
311
312
313 void CVS::undoLast()
314 {
315         // merge the current with the previous version
316         // in a reverse patch kind of way, so that the
317         // result is to revert the last changes.
318         lyxerr << "Sorry not implemented." << endl;
319 }
320
321
322 void CVS::getLog(string const & tmpf)
323 {
324         doVCCommand("cvs log \""
325                     + OnlyFilename(owner_->fileName()) + "\" > " + tmpf,
326                     owner_->filepath);
327 }