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