tests/soup.js
[gitlive] / GitMonitor.js
1
2 var Gio      = imports.gi.Gio;
3 var Gtk      = imports.gi.Gtk;
4 var Notify   = imports.gi.Notify;
5 var GLib     = imports.gi.GLib;
6
7 var Spawn = imports.Spawn;
8 var StatusIcon = imports.StatusIcon.StatusIcon;
9 var Monitor = imports.Monitor.Monitor;
10
11
12
13 var GitMonitor = new Monitor({
14     
15     /**
16      * @property {String} the "gitlive" directory, normally ~/gitlive
17      *  dset by OWNER... - we should do this as a CTOR.
18      *  
19      */
20     gitlive : false,
21     
22     
23     queue : [],
24     queueRunning : false,
25      
26      
27      
28     pause : function() {
29         this.paused = true;
30         this.queue = [];
31         imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PAUSE );
32     },
33     
34     resume : function() {
35         this.paused = false;
36         this.queue = [];
37         imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PLAY );
38         
39         
40     },
41     
42     /**
43      * Start the monitoring
44      * and run the queue every 500 milliseconds..
45      *
46      */
47     start: function() {
48         var _this = this;
49         this.lastAdd = new Date();
50         
51         this.top.forEach(this.monitor, this);
52          
53         GLib.timeout_add(GLib.PRIORITY_LOW, 500, function() {
54             //TIMEOUT", _this.queue.length , _this.queueRunning].join(', '));
55             if (!_this.queue.length || _this.queueRunning) {
56                 return 1;
57             }
58             var last = Math.floor(((new Date()) - _this.lastAdd) / 100);
59             
60             //print("LAST RUN?" + last);
61             
62             if (last < 5) { // wait 1/2 a seconnd before running.
63                 return 1;
64             }
65             //_this.lastAdd = new Date();
66             //return 1;
67         
68             _this.runQueue();
69             return 1;
70         },null,null);
71         
72         try { 
73             var notification = new Notify.Notification({
74                 summary: "Git Live",
75                 body : this.gitlive + "\nMonitoring " + this.monitors.length + " Directories",
76                 timeout : 5
77             });
78     
79             notification.set_timeout(5);
80             notification.show();
81         } catch(e) {
82             print(e.toString());
83         }
84
85     },
86     
87     /**
88      * run the queue.
89      * - pulls the items off the queue 
90      *    (as commands run concurrently and new items may get added while it's running)
91      * - runs the queue items
92      * - pushes upstream.
93      * 
94      */
95     runQueue: function()
96     {
97         
98         if (this.paused) {
99             return;
100         }
101         this.queueRunning = true;
102         var cmds = [];
103         this.queue.forEach(function (q) {
104             cmds.push(q);
105         });
106         this.queue = []; // empty queue!
107         
108         var success = [];
109         var failure = [];
110         var repos = [];
111         var done = [];
112         
113         // first build a array of repo's to work with
114         var repo_list = {};
115         
116         // pull and group.
117         
118         //print(JSON.stringify(cmds));
119         this.paused = true;
120         cmds.forEach(function(cmd) {
121             var gitpath = cmd.shift(); 
122             if (typeof(repo_list[gitpath]) == 'undefined') {
123                 repo_list[gitpath] = new imports.Scm.Git.Repo.Repo( { repopath : gitpath });
124                 repo_list[gitpath].cmds = [];
125                 repo_list[gitpath].pull();
126             }
127             repo_list[gitpath].cmds.push(cmd);
128         });
129         this.paused = false;
130         // build add, remove and commit message list..
131         
132          
133          
134         for (var gitpath in repo_list) {
135             var repo = repo_list[gitpath];
136             var add_files = [];
137             var remove_files = [];
138             var messages = [];
139             //print(JSON.stringify(repo.cmds,null,4));
140             
141             repo.cmds.forEach(function(cmd) {
142                 
143                 var name = cmd.shift();
144                 var arg = cmd.shift();
145                 
146                 switch(name) {
147                     case 'add' :
148                         
149                         if (add_files.indexOf(arg) > -1) {
150                             break;
151                         }
152                         
153                         // if file does not exist.. s,ip
154                         
155                         //if (!GLib.file_test(arg, GLib.FileTest.EXISTS)) {
156                              
157                         //    break;
158                          // }
159         
160                         
161                         add_files.push(arg);
162                         break;
163                     
164                     case 'rm':
165                         
166                         if (add_files.indexOf(arg) > -1) {
167                             break;
168                         }
169                         
170                         // if file exists, do not try and delete it.
171                         if (GLib.file_test(arg, GLib.FileTest.EXISTS)) {
172                             break;
173                         }
174                         
175                         remove_files.push(arg);
176                         break;
177                     
178                     case 'commit' :
179                         
180                         if (messages.indexOf(arg.message) < 0) { 
181                             messages.push(arg.message);
182                         }
183                         break;    
184                 } 
185             });
186             
187             //repo.debug = 1;
188             // these can fail... at present... as we wildcard stuff.
189             print("ADD : "  + JSON.stringify(add_files));
190             
191             // make sure added files do not get removed..
192             remove_files  = remove_files.filter(function(v) {
193                 return add_files.indexOf(v) < 0;
194             });
195             print("REMOVE : "  + JSON.stringify(remove_files));
196             
197             
198             // make sure monitoring is paused so it does not recursively pick up
199             // deletions
200             
201             // -- DO STUFF..
202             
203             repo.add(add_files);
204             
205             repo.remove(remove_files);
206             this.paused = false;
207             
208             
209             try { 
210                 success.push(repo.commit({
211                     reason : messages.join("\n"),
212                     files : add_files  
213                 }));
214                 success.push(repo.push());
215
216             } catch(e) {
217                 failure.push(e.message);
218                 
219             }   
220         }
221         
222         // finally merge all the commit messages.
223          
224         try {
225             // catch notification failures.. so we can carry on..
226             if (success.length) {
227                 print(success.join("\n"));
228                 
229                 var notification = new Notify.Notification({
230                     summary: "Git Live Commited",
231                     body : success.join("\n"),
232                     timeout : 5
233                     
234                 });
235     
236                 notification.set_timeout(5);
237                 notification.show();   
238             }
239             
240             if (failure.length) {
241             
242                 var notification = new Notify.Notification({
243                     summary: "Git Live ERROR!!",
244                     body : failure.join("\n"),
245                     timeout : 5
246                     
247                 });
248     
249                 notification.set_timeout(5); // show errros for longer
250                 notification.show();   
251             }
252         } catch(e) {
253             print(e.toString());
254             
255         }
256         this.queueRunning = false;
257     },
258     
259     shouldIgnore: function(f)
260     {
261         
262         if (this.paused) {
263             return true;
264         }
265         // vim.. what a seriously brain dead program..
266         if (f.name == '4913') {
267             return true;
268         }
269         
270         if (f.name[0] == '.') {
271             // except!
272             if (f.name == '.htaccess') {
273                 return false;
274             }
275             
276             return true;
277         }
278         if (f.name.match(/~$/)) {
279             return true;
280         }
281         if (f.name.match(/^nbproject/)) {
282             return true;
283         }
284         // ignore anything in top level!!!!
285         if (!f.vpath.length) {
286             return true;
287         }
288         
289         return false;
290     },
291     
292     /**
293      * parsePath:
294      * Fill in gitlive, vpath and repo  
295      * 
296      */
297     parsePath: function(f)
298     {
299            
300         var vpath_ar = f.path.substring(this.gitlive.length +1).split('/');
301         
302         f.gitpath = this.gitlive + '/' + vpath_ar.shift();
303         f.vpath =  vpath_ar.join('/');
304         //f.repo = new imports.Scm.Git.Repo({ repopath: f.gitpath })
305         
306         
307     },
308     
309     just_created : {},
310       
311     onChanged : function(src) 
312     { 
313         return; // always ignore this..?
314         //this.parsePath(src);
315     },
316     
317     
318     
319     
320     /**
321      *  results in  git add  + git commit..
322      *
323      */
324     onChangesDoneHint : function(src) 
325     { 
326         this.lastAdd = new Date();
327         this.parsePath(src);
328         if (this.shouldIgnore(src)) {
329             return;
330         }
331         
332        
333         var add_it = false;
334         if (typeof(this.just_created[src.path]) !='undefined') {
335             delete this.just_created[src.path];
336             
337             this.queue.push( 
338                 [ src.gitpath,  'add', src.vpath ],
339                 [ src.gitpath,  'commit',    { message: src.vpath} ] 
340                 
341             );
342          
343             return;
344         }
345         
346         this.queue.push( 
347             [ src.gitpath,  'add', src.vpath ],
348             [ src.gitpath,  'commit',  {  message: src.vpath} ]
349
350             
351         );
352     },
353     onDeleted : function(src) 
354     { 
355         this.lastAdd = new Date();
356         this.parsePath(src);
357         if (this.shouldIgnore(src)) {
358             return;
359         }
360         // should check if monitor needs removing..
361         // it should also check if it was a directory.. - so we dont have to commit all..
362         
363         
364         this.queue.push( 
365             [ src.gitpath, 'rm' , src.vpath ],
366             [ src.gitpath, 'commit', { all: true, message: src.vpath} ]
367             
368         );
369     
370         
371     },
372     onCreated : function(src) 
373     { 
374         this.lastAdd = new Date();
375         this.parsePath(src);
376         if (this.shouldIgnore(src)) {
377             return;
378         }
379         
380         if (!GLib.file_test(src.path, GLib.FileTest.IS_DIR)) {
381             this.just_created[src.path] = true;
382             return; // we do not handle file create flags... - use done hint.
383         }
384         // director has bee created
385         this.monitor(src.path);
386         
387         this.queue.push( 
388             [ src.gitpath, 'add' , src.vpath,  { all: true } ],
389             [ src.gitpath, 'commit' , { all: true, message: src.vpath} ]
390             
391         );
392         
393         
394     },
395     onAttributeChanged : function(src)
396     { 
397         this.lastAdd = new Date();
398         this.parsePath(src);
399         if (this.shouldIgnore(src)) {
400             return;
401         }
402         
403         this.queue.push(
404                         
405             //[ src.gitpath, 'commit' ,  src.vpath, { message: src.vpath} ]
406             [ src.gitpath, 'add' ,  src.vpath ],
407              [ src.gitpath, 'commit' ,    {  message: "Attribute Changed :" + src.vpath} ]
408         );
409  
410     
411     },
412     
413     onMoved : function(src,dest)
414     { 
415         this.lastAdd = new Date();
416         this.parsePath(src);
417         this.parsePath(dest);
418         
419         if (src.gitpath != dest.gitpath) {
420             this.onDeleted(src);
421             this.onCreated(dest);
422             this.onChangedDoneHint(dest);
423             return;
424         }
425         // needs to handle move to/from unsupported types..
426         
427         if (this.shouldIgnore(src)) {
428             return;
429         }
430         if (this.shouldIgnore(dest)) {
431             return;
432         }
433         
434         this.queue.push( 
435            // [ src.gitpath, 'mv',  '-k', src.vpath, dest.vpath ],
436              [ src.gitpath, 'add',    dest.vpath ],
437              [ src.gitpath, 'rm',    src.vpath ],
438              
439             [ src.gitpath, 'commit' , 
440                 { message:   'MOVED ' + src.vpath +' to ' + dest.vpath}
441             ]
442         );
443          
444     }
445           
446     
447 });
448  
449