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