Updated towards 0.61.09 release
[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$
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 #include "general.h"
47
48 #endif
49
50 /* === U S I N G =========================================================== */
51
52 using namespace std;
53 using namespace etl;
54 using namespace synfig;
55 using namespace synfigapp;
56
57 /* === M A C R O S ========================================================= */
58
59 #define cvs_command             synfig::String("cvs -z4")
60
61 #ifndef WIN32
62 #define HAVE_STRPTIME
63 #endif
64
65 #ifdef __APPLE__
66 time_t _daylight_() { time_t t(time(0)); return localtime(&t)->tm_gmtoff; }
67 #define daylight _daylight_()
68 #endif
69
70 /* === G L O B A L S ======================================================= */
71
72 /* === P R O C E D U R E S ================================================= */
73
74 /* === M E T H O D S ======================================================= */
75
76 CVSInfo::CVSInfo(const synfig::String& file_name)
77 {
78         update_available_=false;
79         set_file_name(file_name);
80 }
81
82 CVSInfo::CVSInfo()
83 {
84         update_available_=false;
85 }
86
87 CVSInfo::~CVSInfo()
88 {
89 }
90
91 void
92 CVSInfo::set_file_name(const synfig::String& file_name)
93 {
94         file_name_=file_name;
95
96         std::ifstream file((dirname(file_name_)+"/CVS/Root").c_str());
97
98         if(file)
99         {
100                 in_sandbox_=true;
101                 calc_repository_info();
102         }
103         else
104                 in_sandbox_=false;
105 }
106
107 void
108 CVSInfo::calc_repository_info()
109 {
110 #ifdef _DEBUG
111         synfig::info("in_sandbox() = %d",in_sandbox());
112 #endif
113
114         if(!in_sandbox_)
115                 return;
116
117         std::ifstream file((dirname(file_name_)+"/CVS/Entries").c_str());
118
119         while(file)
120         {
121                 String line;
122                 getline(file,line);
123                 if(line.find(basename(file_name_))!=String::npos)
124                 {
125                         in_repository_=true;
126                         String::size_type s,f;
127
128                         // Grab the version
129                         s=line.find('/',1);
130                         assert(s!=String::npos);
131                         s++;
132                         f=line.find('/',s+1);
133                         assert(f!=String::npos);
134                         cvs_version_=String(line,s,f-s);
135
136                         // Grab the time
137 #ifdef HAVE_STRPTIME
138                         s=f+1;
139                         f=line.find('/',s+1);
140                         assert(f!=String::npos);
141                         tm time_struct;
142                         strptime(String(line,s,f-s).c_str(),"%c",&time_struct);
143                         original_timestamp_=mktime(&time_struct);
144 #endif
145
146                         if(
147                                 system(strprintf(
148                                         "cd '%s' && cvs status '%s' | grep -q -e 'Needs Patch'",
149                                         dirname(file_name_).c_str(),
150                                         basename(file_name_).c_str()
151                                 ).c_str())==0
152                         )
153                         {
154                                 synfig::info("UPDATE_AVAILABLE=TRUE");
155                                 update_available_=true;
156                         }
157                         else
158                         {
159                                 system(strprintf(
160                                         "cd '%s' && cvs status '%s'",
161                                         dirname(file_name_).c_str(),
162                                         basename(file_name_).c_str()
163                                 ).c_str());
164                                 synfig::info("UPDATE_AVAILABLE=FALSE");
165                                 update_available_=false;
166                         }
167
168
169 #ifdef _DEBUG
170                         synfig::info("in_repository() = %d",in_repository());
171                         synfig::info("get_cvs_version() = %s",get_cvs_version().c_str());
172                         synfig::info("get_original_timestamp() = %s",ctime(&get_original_timestamp()));
173                         time_t t(get_current_timestamp());
174                         synfig::info("get_current_timestamp() = %s",ctime(&t));
175                         synfig::info("get_cvs_root() = %s",get_cvs_root().c_str());
176                         synfig::info("get_cvs_module() = %s",get_cvs_module().c_str());
177 #endif
178                         return;
179                 }
180         }
181
182         in_repository_=false;
183         cvs_version_.clear();
184         original_timestamp_=0;
185
186 #ifdef _DEBUG
187         synfig::info("in_repository() = %d",in_repository());
188 #endif
189 }
190
191 bool
192 CVSInfo::in_sandbox()const
193 {
194         return in_sandbox_;
195 }
196
197 bool
198 CVSInfo::in_repository()const
199 {
200         if(!in_sandbox_)
201                 return false;
202         return in_repository_;
203 }
204
205 bool
206 CVSInfo::is_modified()const
207 {
208         if(!in_sandbox() || !in_repository())
209                 return false;
210 #ifdef _DEBUG
211         synfig::info("%d-%d=%d",get_current_timestamp(),get_original_timestamp(),get_current_timestamp()-get_original_timestamp());
212 #endif
213         return get_current_timestamp()!=get_original_timestamp() && abs(get_current_timestamp()-get_original_timestamp())!=3600;
214 }
215
216 bool
217 CVSInfo::is_updated()const
218 {
219         return update_available_;
220 }
221
222 const synfig::String&
223 CVSInfo::get_cvs_version()const
224 {
225         return cvs_version_;
226 }
227
228 const time_t&
229 CVSInfo::get_original_timestamp()const
230 {
231         return original_timestamp_;
232 }
233
234 time_t
235 CVSInfo::get_current_timestamp()const
236 {
237         struct stat st;
238         if(stat(file_name_.c_str(),&st)<0)
239         {
240                 synfig::error("Unable to get file stats");
241                 return false;
242         }
243         time_t ret((daylight-1)*3600);
244         //ret+=timezone;
245         ret+=st.st_mtime;
246         return ret;
247 }
248
249 synfig::String
250 CVSInfo::get_cvs_root()const
251 {
252         if(!in_sandbox_)
253                 return synfig::String();
254
255         std::ifstream file((dirname(file_name_)+"/CVS/Root").c_str());
256
257         if(file)
258         {
259                 String ret;
260                 getline(file,ret);
261                 return ret;
262         }
263
264         return synfig::String();
265 }
266
267 synfig::String
268 CVSInfo::get_cvs_module()const
269 {
270         if(!in_sandbox_)
271                 return synfig::String();
272
273         std::ifstream file((dirname(file_name_)+"/CVS/Repository").c_str());
274
275         if(file)
276         {
277                 String ret;
278                 getline(file,ret);
279                 return ret;
280         }
281
282         return synfig::String();
283 }
284
285 // This function pre-processes the message so that we
286 // don't get any CVS syntax errors.
287 inline synfig::String fix_msg(const synfig::String& message)
288 {
289         synfig::String ret;
290         int i;
291         for(i=0;i<(int)message.size();i++)
292         {
293                 if(message[i]=='\'')
294                         ret+="'\"'\"'";
295                 else
296                         ret+=message[i];
297         }
298         return ret;
299 }
300
301 void
302 CVSInfo::cvs_add(const synfig::String& message)
303 {
304         if(!in_sandbox_)
305         {
306                 synfig::error("cvs_add(): Not in a sand box");
307                 throw int();
308                 return;
309         }
310
311         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()));
312
313         int ret(system(command.c_str()));
314
315         calc_repository_info();
316
317         switch(ret)
318         {
319         case 0:
320                 break;
321         default:
322                 synfig::error("Unknown errorcode %d (\"%s\")",ret,command.c_str());
323                 throw(ret);
324                 break;
325         }
326 }
327
328 void
329 CVSInfo::cvs_update()
330 {
331         if(!in_sandbox_)
332         {
333                 synfig::error("cvs_update(): Not in a sand box");
334                 throw int();
335                 return;
336         }
337
338         synfig::String command(strprintf("cd '%s' && %s update '%s'",dirname(file_name_).c_str(),cvs_command.c_str(),basename(file_name_).c_str()));
339
340         int ret(system(command.c_str()));
341
342         calc_repository_info();
343
344         switch(ret)
345         {
346         case 0:
347                 break;
348         default:
349                 synfig::error("Unknown errorcode %d (\"%s\")",ret,command.c_str());
350                 throw(ret);
351                 break;
352         }
353 }
354
355 void
356 CVSInfo::cvs_commit(const synfig::String& message)
357 {
358         if(!in_sandbox_)
359         {
360                 synfig::error("cvs_commit(): Not in a sand box");
361                 throw int();
362                 return;
363         }
364
365         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()));
366
367         int ret(system(command.c_str()));
368
369         calc_repository_info();
370
371         switch(ret)
372         {
373         case 0:
374                 break;
375         default:
376                 synfig::error("Unknown errorcode %d (\"%s\")",ret,command.c_str());
377                 if(is_modified())
378                         throw(ret);
379                 break;
380         }
381 }