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