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