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