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