fix
[gitlive] / gitlive.js
1 #!/usr/bin/seed
2 ///<script type="text/javascript">
3 /**
4 * Git Live
5
6 * inotify hooks for ~/gitlive
7 * that commit and push any changes made.
8 * Bit like a revision controled backed up file system!?
9
10
11 */
12
13 GIRepository      = imports.gi.GIRepository
14 GLib        = imports.gi.GLib;
15
16 //print(JSON.stringify(GI, null,4));
17 // we add this in, as it appears to get lost sometimes if we set it using the ENV. variable in builder.sh
18 //GI.Repository.prepend_search_path(GLib.get_home_dir() + '/.Builder/girepository-1.1');
19 GIRepository.Repository.prepend_search_path(GLib.get_home_dir() + '/.Builder/girepository-1.2');
20
21 var Gio      = imports.gi.Gio;
22 var Gtk      = imports.gi.Gtk;
23 var Notify = imports.gi.Notify;
24
25 var Spawn = imports.Spawn;
26 var Git = imports.Git;
27 var StatusIcon = imports.StatusIcon.StatusIcon;
28 var Monitor = imports.Monitor.Monitor;
29
30
31 //File = imports[__script_path__+'/../introspection-doc-generator/File.js'].File
32 Gtk.init (null, null);
33
34 var gitlive = GLib.get_home_dir() + "/gitlive";
35
36 if (!GLib.file_test(gitlive, GLib.FileTest.IS_DIR)) {
37     var msg = new Gtk.MessageDialog({message_type:
38         Gtk.MessageType.INFO, buttons : Gtk.ButtonsType.OK, text: "GIT Live - ~/gitlive does not exist."});
39     msg.run();
40     msg.destroy();
41     
42     Seed.quit();
43 }
44
45  
46 var monitor = new Monitor({
47     
48     queue : [],
49     queueRunning : false,
50      
51     start: function() {
52         var _this = this;
53         this.lastAdd = new Date();
54          
55         GLib.timeout_add(GLib.PRIORITY_LOW, 500, function() {
56             //TIMEOUT", _this.queue.length , _this.queueRunning].join(', '));
57             if (!_this.queue.length || _this.queueRunning) {
58                 return 1;
59             }
60             var last = Math.floor(((new Date()) - this.lastAdd) / 100);
61             if (last < 4) { // wait 1/2 a seconnd before running.
62                 return 1;
63             }
64             _this.runQueue();
65             return 1;
66         },null,null);
67         
68         try { 
69             var notification = new Notify.Notification({
70                 summary: "Git Live",
71                 body : gitlive + "\nMonitoring " + this.monitors.length + " Directories",
72                 timeout : 5
73             });
74     
75             notification.set_timeout(5);
76             notification.show();
77         } catch(e) {
78             print(e.toString());
79         }
80
81     },
82     
83     /**
84      * run the queue.
85      * - pulls the items off the queue 
86      *    (as commands run concurrently and new items may get added while it's running)
87      * - runs the queue items
88      * - pushes upstream.
89      * 
90      */
91     runQueue: function()
92     {
93         this.queueRunning = true;
94         var cmds = [];
95         this.queue.forEach(function (q) {
96             cmds.push(q);
97         });
98         this.queue = []; // empty queue!
99         
100         var success = [];
101         var failure = [];
102         var repos = [];
103         var done = [];
104         cmds.forEach(function(cmd) {
105             // prevent duplicate calls..
106             if (done.indexOf(cmd.join(',')) > -1) {
107                 return;
108             }
109             done.push(cmd.join(','));
110             
111             if (repos.indexOf(cmd[0]) < 0) {
112                 repos.push(cmd[0]);
113                 Git.run(cmd[0] , 'pull'); // pull before we push!
114             }
115             var sp = Git.run.apply(Git,cmd);
116              
117             switch (sp.result * 1) {
118                 case 0: // success:
119                     success.push(sp.args.join(' '));
120                     if (sp.output.length) success.push(sp.output + '');
121                   // if (sp.stderr.length) success.push(sp.stderr + '');
122                     break;
123                 default: 
124                     failure.push(sp.args.join(' '));
125                     if (sp.output.length) failure.push(sp.output);
126                     if (sp.stderr.length) failure.push(sp.stderr);
127                     break;
128             }
129             
130         });
131          
132         // push upstream.
133         repos.forEach(function(r) {
134             var sp = Git.run(r , 'push', { all: true } );
135             if (sp.length) {
136                 success.push(sp);
137             }
138             
139         });
140         try {
141             // catch notification failures.. so we can carry on..
142             if (success.length) {
143                 print(success.join("\n"));
144                 
145                 var notification = new Notify.Notification({
146                     summary: "Git Live Commited",
147                     body : success.join("\n"),
148                     timeout : 5
149                     
150                 });
151     
152                 notification.set_timeout(5);
153                 notification.show();   
154             }
155             
156             if (failure.length) {
157             
158                 var notification = new Notify.Notification({
159                     summary: "Git Live ERROR!!",
160                     body : failure.join("\n"),
161                     timeout : 5
162                     
163                 });
164     
165                 notification.set_timeout(5); // show errros for longer
166                 notification.show();   
167             }
168         } catch(e) {
169             print(e.toString());
170             
171         }
172         this.queueRunning = false;
173     },
174     
175     shouldIgnore: function(f)
176     {
177         if (f.name[0] == '.') {
178             // except!
179             if (f.name == '.htaccess') {
180                 return false;
181             }
182             
183             return true;
184         }
185         if (f.name.match(/~$/)) {
186             return true;
187         }
188         // ignore anything in top level!!!!
189         if (!f.vpath.length) {
190             return true;
191         }
192         
193         return false;
194         
195     },
196     
197     parsePath: function(f) {
198            
199         var vpath_ar = f.path.substring(gitlive.length +1).split('/');
200         
201         f.gitpath = gitlive + '/' + vpath_ar.shift();
202         f.vpath =  vpath_ar.join('/');
203         
204         
205     },
206     
207     just_created : {},
208       
209     onChanged : function(src) 
210     { 
211         return; // always ignore this..?
212         //this.parsePath(src);
213     },
214 <<<<<<< HEAD
215     
216     /**
217      *  results in  git add  + git commit..
218      *
219      */
220     
221 =======
222 >>>>>>> a198afafefd3a4f8857af843a2a8433158ee8720
223     onChangesDoneHint : function(src) 
224     { 
225         this.parsePath(src);
226         if (this.shouldIgnore(src)) {
227             return;
228         }
229         
230        
231         var add_it = false;
232         if (typeof(this.just_created[src.path]) !='undefined') {
233             delete this.just_created[src.path];
234             this.lastAdd = new Date();
235             this.queue.push( 
236                 [ src.gitpath,  'add', src.vpath ],
237                 [ src.gitpath,  'commit',  src.vpath, { message: src.vpath} ] 
238                 
239             );
240          
241             return;
242         }
243         this.lastAdd = new Date();
244         this.queue.push( 
245             [ src.gitpath,  'add', src.vpath ],
246             [ src.gitpath,  'commit', src.vpath, {  message: src.vpath} ]
247
248             
249         );
250        
251
252     },
253     onDeleted : function(src) 
254     { 
255         this.parsePath(src);
256         if (this.shouldIgnore(src)) {
257             return;
258         }
259         // should check if monitor needs removing..
260         // it should also check if it was a directory.. - so we dont have to commit all..
261         
262         this.lastAdd = new Date();
263         this.queue.push( 
264             [ src.gitpath, 'rm' , src.vpath ],
265             [ src.gitpath, 'commit', { all: true, message: src.vpath} ]
266             
267         );
268     
269         
270     },
271     onCreated : function(src) 
272     { 
273         this.parsePath(src);
274         if (this.shouldIgnore(src)) {
275             return;
276         }
277         
278         if (!GLib.file_test(src.path, GLib.FileTest.IS_DIR)) {
279             this.just_created[src.path] = true;
280             return; // we do not handle file create flags... - use done hint.
281         }
282         // director has bee created
283         this.monitor(src.path);
284         this.lastAdd = new Date();
285         this.queue.push( 
286             [ src.gitpath, 'add' , src.vpath,  { all: true } ],
287             [ src.gitpath, 'commit' , { all: true, message: src.vpath} ]
288             
289         );
290         
291         
292     },
293     onAttributeChanged : function(src) { 
294         this.parsePath(src);
295         if (this.shouldIgnore(src)) {
296             return;
297         }
298         this.lastAdd = new Date();
299         this.queue.push( 
300             [ src.gitpath, 'commit' ,  src.vpath, { message: src.vpath} ]
301         );
302  
303     
304     },
305     
306     onMoved : function(src,dest)
307     { 
308         this.parsePath(src);
309         this.parsePath(dest);
310         
311         if (src.gitpath != dest.gitpath) {
312             this.onDeleted(src);
313             this.onCreated(dest);
314             this.onChangedDoneHint(dest);
315             return;
316         }
317         // needs to handle move to/from unsupported types..
318         
319         if (this.shouldIgnore(src)) {
320             return;
321         }
322         if (this.shouldIgnore(dest)) {
323             return;
324         }
325         this.lastAdd = new Date();
326         this.queue.push( 
327             [ src.gitpath, 'mv',  '-k', src.vpath, dest.vpath ],
328             [ src.gitpath, 'commit' ,  src.vpath, dest.vpath ,
329                 { message:   'MOVED ' + src.vpath +' to ' + dest.vpath} ]
330         );
331          
332     }
333           
334     
335 });
336  
337  
338   
339
340 function errorDialog(data) {
341     var msg = new Gtk.MessageDialog({
342             message_type: Gtk.MessageType.ERROR, 
343             buttons : Gtk.ButtonsType.OK, 
344             text: data
345     });
346     msg.run();
347     msg.destroy();
348 }
349
350  
351
352
353
354 //
355 // need a better icon...
356
357
358 StatusIcon.init();   
359
360
361 Notify.init("gitlive");
362
363 monitor.add(GLib.get_home_dir() + "/gitlive");
364 monitor.start();
365 Gtk.main();
366 //icon.signal["activate"].connect(on_left_click);
367