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<GitMontitorQueue>();
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(i);
204     
205                 var name = cmd.shift();
206                 var arg = cmd.shift();
207                 
208                 switch(cmd.name) {
209                     case "add" :
210                         
211                         if (GitMontitorQueue.indexOfAdd(add_files, cmd.add) > -1) {
212                            break;
213                         }
214         
215                         
216                         add_files.append_val(cmd);
217                         break;
218                     
219                     case 'rm':
220                         if (GitMontitorQueue.indexOfAdd(add_files, cmd.rm) > -1 ) {
221                            break;
222                         }
223                         
224                         // if file exists, do not try and delete it.
225                         if (GLib.file_test(cmd.rm, GLib.FileTest.EXISTS)) {
226                             break;
227                         }
228                         
229                         remove_files.append_val(cmd);
230                         break;
231                     
232                     case 'commit' :
233                         if (GitMontitorQueue.indexOfMessage(messages, cmd.message) > -1 ) {
234                            break;
235                         }
236                          
237                         messages.append_val(cmd);
238                         
239                         break;    
240                 } 
241             });
242             
243             //repo.debug = 1;
244             // these can fail... at present... as we wildcard stuff.
245             print("ADD : "  + JSON.stringify(add_files));
246             
247             // make sure added files do not get removed..
248             remove_files  = remove_files.filter(function(v) {
249                 return add_files.indexOf(v) < 0;
250             });
251             print("REMOVE : "  + JSON.stringify(remove_files));
252             
253             
254             // make sure monitoring is paused so it does not recursively pick up
255             // deletions
256             
257             // -- DO STUFF..
258             
259             repo.add(add_files);
260             
261             repo.remove(remove_files);
262             this.paused = false;
263             
264             
265             try { 
266                 success.push(repo.commit({
267                     reason : messages.join("\n"),
268                     files : add_files  
269                 }));
270                 success.push(repo.push());
271
272             } catch(e) {
273                 failure.push(e.message);
274                 
275             }   
276         }
277         
278         // finally merge all the commit messages.
279          
280         try {
281             // catch notification failures.. so we can carry on..
282             if (success.length) {
283                 print(success.join("\n"));
284                 
285                 var notification = new Notify.Notification({
286                     summary: "Git Live Commited",
287                     body : success.join("\n"),
288                     timeout : 5
289                     
290                 });
291     
292                 notification.set_timeout(5);
293                 notification.show();   
294             }
295             
296             if (failure.length) {
297             
298                 var notification = new Notify.Notification({
299                     summary: "Git Live ERROR!!",
300                     body : failure.join("\n"),
301                     timeout : 5
302                     
303                 });
304     
305                 notification.set_timeout(5); // show errros for longer
306                 notification.show();   
307             }
308         } catch(e) {
309             print(e.toString());
310             
311         }
312         this.queueRunning = false;
313     },
314