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