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.name);
272
273             } catch(Error e) {
274                 failure.push(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                 print(success.join("\n"));
285                 
286                 var notification = new Notify.Notification({
287                     summary: "Git Live Commited",
288                     body : success.join("\n"),
289                     timeout : 5
290                     
291                 });
292     
293                 notification.set_timeout(5);
294                 notification.show();   
295             }
296             
297             if (failure.length) {
298             
299                 var notification = new Notify.Notification({
300                     summary: "Git Live ERROR!!",
301                     body : failure.join("\n"),
302                     timeout : 5
303                     
304                 });
305     
306                 notification.set_timeout(5); // show errros for longer
307                 notification.show();   
308             }
309         } catch(e) {
310             print(e.toString());
311             
312         }
313         this.queueRunning = false;
314     },
315