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