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