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