more updates
[synfig.git] / synfig-studio / trunk / src / synfigapp / cvs.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file cvs.cpp
3 **      \brief Template File
4 **
5 **      $Id: cvs.cpp,v 1.1.1.1 2005/01/07 03:34:37 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #ifdef USING_PCH
26 #       include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #       include <config.h>
30 #endif
31
32 #include "cvs.h"
33 #include <ETL/stringf>
34 #include <fstream>
35 #include <iostream>
36 #include <synfig/general.h>
37 #include <stdlib.h>
38
39
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 //#include <unistd.h>
43
44 #include <cassert>
45
46 #endif
47
48 /* === U S I N G =========================================================== */
49
50 using namespace std;
51 using namespace etl;
52 using namespace synfig;
53 using namespace synfigapp;
54
55 /* === M A C R O S ========================================================= */
56
57 #define cvs_command             synfig::String("cvs -z4")
58
59 #ifndef WIN32
60 #define HAVE_STRPTIME
61 #endif
62
63 #ifdef __APPLE__
64 time_t _daylight_() { time_t t(time(0)); return localtime(&t)->tm_gmtoff; }
65 #define daylight _daylight_()
66 #endif
67
68 /* === G L O B A L S ======================================================= */
69
70 /* === P R O C E D U R E S ================================================= */
71
72 /* === M E T H O D S ======================================================= */
73
74 CVSInfo::CVSInfo(const synfig::String& file_name)
75 {
76         update_available_=false;
77         set_file_name(file_name);
78 }
79
80 CVSInfo::CVSInfo()
81 {
82         update_available_=false;
83 }
84
85 CVSInfo::~CVSInfo()
86 {
87 }
88
89 void
90 CVSInfo::set_file_name(const synfig::String& file_name)
91 {
92         file_name_=file_name;
93         
94         std::ifstream file((dirname(file_name_)+"/CVS/Root").c_str());
95
96         if(file)
97         {
98                 in_sandbox_=true;
99                 calc_repository_info();
100         }
101         else
102                 in_sandbox_=false;
103 }
104
105 void
106 CVSInfo::calc_repository_info()
107 {
108 #ifdef _DEBUG
109         synfig::info("in_sandbox() = %d",in_sandbox());
110 #endif
111         
112         if(!in_sandbox_)
113                 return;
114         
115         std::ifstream file((dirname(file_name_)+"/CVS/Entries").c_str());
116
117         while(file)
118         {
119                 String line;
120                 getline(file,line);
121                 if(line.find(basename(file_name_))!=String::npos)
122                 {
123                         in_repository_=true;
124                         String::size_type s,f;
125                         
126                         // Grab the version
127                         s=line.find('/',1);
128                         assert(s!=String::npos);
129                         s++;
130                         f=line.find('/',s+1);
131                         assert(f!=String::npos);
132                         cvs_version_=String(line,s,f-s);
133                         
134                         // Grab the time
135 #ifdef HAVE_STRPTIME
136                         s=f+1;
137                         f=line.find('/',s+1);
138                         assert(f!=String::npos);
139                         tm time_struct;
140                         strptime(String(line,s,f-s).c_str(),"%c",&time_struct);
141                         original_timestamp_=mktime(&time_struct);
142 #endif
143                         
144                         if(
145                                 system(strprintf(
146                                         "cd '%s' && cvs status '%s' | grep -q -e 'Needs Patch'",
147                                         dirname(file_name_).c_str(),
148                                         basename(file_name_).c_str()
149                                 ).c_str())==0
150                         )
151                         {
152                                 synfig::info("UPDATE_AVAILABLE=TRUE");
153                                 update_available_=true;
154                         }
155                         else
156                         {
157                                 system(strprintf(
158                                         "cd '%s' && cvs status '%s'",
159                                         dirname(file_name_).c_str(),
160                                         basename(file_name_).c_str()
161                                 ).c_str());
162                                 synfig::info("UPDATE_AVAILABLE=FALSE");
163                                 update_available_=false;
164                         }
165                                 
166                         
167 #ifdef _DEBUG
168                         synfig::info("in_repository() = %d",in_repository());
169                         synfig::info("get_cvs_version() = %s",get_cvs_version().c_str());
170                         synfig::info("get_original_timestamp() = %s",ctime(&get_original_timestamp()));
171                         time_t t(get_current_timestamp());
172                         synfig::info("get_current_timestamp() = %s",ctime(&t));
173                         synfig::info("get_cvs_root() = %s",get_cvs_root().c_str());
174                         synfig::info("get_cvs_module() = %s",get_cvs_module().c_str());
175 #endif                  
176                         return;
177                 }
178         }
179
180         in_repository_=false;
181         cvs_version_.clear();
182         original_timestamp_=0;
183
184 #ifdef _DEBUG
185         synfig::info("in_repository() = %d",in_repository());
186 #endif
187 }
188
189 bool
190 CVSInfo::in_sandbox()const
191 {
192         return in_sandbox_;
193 }
194
195 bool
196 CVSInfo::in_repository()const
197 {
198         if(!in_sandbox_)
199                 return false;
200         return in_repository_;
201 }
202
203 bool
204 CVSInfo::is_modified()const
205 {
206 #ifdef _DEBUG
207         synfig::info("%d-%d=%d",get_current_timestamp(),get_original_timestamp(),get_current_timestamp()-get_original_timestamp());
208 #endif
209         if(!in_sandbox() || !in_repository())
210                 return false;
211         return get_current_timestamp()!=get_original_timestamp() && abs(get_current_timestamp()-get_original_timestamp())!=3600;
212 }
213
214 bool
215 CVSInfo::is_updated()const
216 {
217         return update_available_;
218 }
219
220 const synfig::String&
221 CVSInfo::get_cvs_version()const
222 {
223         return cvs_version_;
224 }
225
226 const time_t&
227 CVSInfo::get_original_timestamp()const
228 {
229         return original_timestamp_;
230 }
231
232 time_t
233 CVSInfo::get_current_timestamp()const
234 {
235         struct stat st;
236         if(stat(file_name_.c_str(),&st)<0)
237         {
238                 synfig::error("Unable to get file stats");
239                 return false;
240         }
241         return st.st_mtime+timezone+(daylight-1)*3600;
242 }
243
244 synfig::String
245 CVSInfo::get_cvs_root()const
246 {
247         if(!in_sandbox_)
248                 return synfig::String();
249         
250         std::ifstream file((dirname(file_name_)+"/CVS/Root").c_str());
251
252         if(file)
253         {
254                 String ret;
255                 getline(file,ret);
256                 return ret;
257         }
258
259         return synfig::String();
260 }
261
262 synfig::String
263 CVSInfo::get_cvs_module()const
264 {
265         if(!in_sandbox_)
266                 return synfig::String();
267
268         std::ifstream file((dirname(file_name_)+"/CVS/Repository").c_str());
269
270         if(file)
271         {
272                 String ret;
273                 getline(file,ret);
274                 return ret;
275         }
276
277         return synfig::String();
278 }
279
280 // This function pre-processes the message so that we
281 // don't get any CVS syntax errors.
282 inline synfig::String fix_msg(const synfig::String& message)
283 {
284         synfig::String ret;
285         int i;
286         for(i=0;i<(int)message.size();i++)
287         {
288                 if(message[i]=='\'')
289                         ret+="'\"'\"'";
290                 else
291                         ret+=message[i];
292         }
293         return ret;
294 }
295
296 void
297 CVSInfo::cvs_add(const synfig::String& message)
298 {
299         if(!in_sandbox_)
300         {
301                 synfig::error("cvs_add(): Not in a sand box");
302                 throw int();
303                 return;
304         }
305         
306         synfig::String command(strprintf("cd '%s' && %s add -m '%s' '%s'",dirname(file_name_).c_str(),cvs_command.c_str(),fix_msg(message).c_str(),basename(file_name_).c_str()));
307         
308         int ret(system(command.c_str()));
309         
310         calc_repository_info();
311
312         switch(ret)
313         {
314         case 0:
315                 break;
316         default:
317                 synfig::error("Unknown errorcode %d (\"%s\")",ret,command.c_str());
318                 throw(ret);
319                 break;
320         }
321 }
322         
323 void
324 CVSInfo::cvs_update()
325 {
326         if(!in_sandbox_)
327         {
328                 synfig::error("cvs_update(): Not in a sand box");
329                 throw int();
330                 return;
331         }
332         
333         synfig::String command(strprintf("cd '%s' && %s update '%s'",dirname(file_name_).c_str(),cvs_command.c_str(),basename(file_name_).c_str()));
334         
335         int ret(system(command.c_str()));
336
337         calc_repository_info();
338         
339         switch(ret)
340         {
341         case 0:
342                 break;
343         default:
344                 synfig::error("Unknown errorcode %d (\"%s\")",ret,command.c_str());
345                 throw(ret);
346                 break;
347         }
348 }
349         
350 void
351 CVSInfo::cvs_commit(const synfig::String& message)
352 {
353         if(!in_sandbox_)
354         {
355                 synfig::error("cvs_commit(): Not in a sand box");
356                 throw int();
357                 return;
358         }
359         
360         synfig::String command(strprintf("cd '%s' && %s commit -m '%s' '%s'",dirname(file_name_).c_str(),cvs_command.c_str(),fix_msg(message).c_str(),basename(file_name_).c_str()));
361         
362         int ret(system(command.c_str()));
363
364         calc_repository_info();
365         
366         switch(ret)
367         {
368         case 0:
369                 break;
370         default:
371                 synfig::error("Unknown errorcode %d (\"%s\")",ret,command.c_str());
372                 if(is_modified())
373                         throw(ret);
374                 break;
375         }
376 }