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