Final User interface tweaks to basic commit code (shows dialogs while it does stuff)
[gitlive] / GitMonitor.js
1
2 var Gio      = imports.gi.Gio;
3 var Gtk      = imports.gi.Gtk;
4 var Notify   = imports.gi.Notify;
5 var GLib     = imports.gi.GLib;
6
7 var Spawn = imports.Spawn;
8 var StatusIcon = imports.StatusIcon.StatusIcon;
9 var Monitor = imports.Monitor.Monitor;
10
11
12
13 var GitMonitor = new Monitor({
14     
15     /**
16      * @property {String} the "gitlive" directory, normally ~/gitlive
17      *  dset by OWNER... - we should do this as a CTOR.
18      *  
19      */
20     gitlive : false,
21     
22     
23     queue : [],
24     queueRunning : false,
25      
26      
27      
28     pause : function() {
29         this.paused = true;
30         this.queue = [];
31         imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PAUSE );
32     },
33     
34     resume : function() {
35         this.paused = false;
36         this.queue = [];
37         imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PLAY );
38         
39         
40     },
41     
42     
43     start: function() {
44         var _this = this;
45         this.lastAdd = new Date();
46         
47         this.top.forEach(this.monitor, this);
48          
49         GLib.timeout_add(GLib.PRIORITY_LOW, 500, function() {
50             //TIMEOUT", _this.queue.length , _this.queueRunning].join(', '));
51             if (!_this.queue.length || _this.queueRunning) {
52                 return 1;
53             }
54             var last = Math.floor(((new Date()) - this.lastAdd) / 100);
55             if (last < 4) { // wait 1/2 a seconnd before running.
56                 return 1;
57             }
58             _this.runQueue();
59             return 1;
60         },null,null);
61         
62         try { 
63             var notification = new Notify.Notification({
64                 summary: "Git Live",
65                 body : this.gitlive + "\nMonitoring " + this.monitors.length + " Directories",
66                 timeout : 5
67             });
68     
69             notification.set_timeout(5);
70             notification.show();
71         } catch(e) {
72             print(e.toString());
73         }
74
75     },
76     
77     /**
78      * run the queue.
79      * - pulls the items off the queue 
80      *    (as commands run concurrently and new items may get added while it's running)
81      * - runs the queue items
82      * - pushes upstream.
83      * 
84      */
85     runQueue: function()
86     {
87         
88         if (this.paused) {
89             return;
90         }
91         this.queueRunning = true;
92         var cmds = [];
93         this.queue.forEach(function (q) {
94             cmds.push(q);
95         });
96         this.queue = []; // empty queue!
97         
98         var success = [];
99         var failure = [];
100         var repos = [];
101         var done = [];
102         
103         // first build a array of repo's to work with
104         var repo_list = {};
105         
106         // pull and group.
107         
108         //print(JSON.stringify(cmds));
109         
110         cmds.forEach(function(cmd) {
111             var gitpath = cmd.shift(); 
112             if (typeof(repo_list[gitpath]) == 'undefined') {
113                 repo_list[gitpath] = new imports.Scm.Git.Repo.Repo( { repopath : gitpath });
114                 repo_list[gitpath].cmds = [];
115                 repo_list[gitpath].pull();
116             }
117             repo_list[gitpath].cmds.push(cmd);
118         });
119         
120         // build add, remove and commit message list..
121         
122          
123         for (var gitpath in repo_list) {
124             var repo = repo_list[gitpath];
125             var add_files = [];
126             var remove_files = [];
127             var messages = [];
128             repo.cmds.forEach(function(cmd) {
129                 //print(JSON.stringify(cmd));
130                 var name = cmd.shift();
131                 var arg = cmd.shift();
132                 
133                 switch(name) {
134                     case 'add' :
135                         if (add_files.indexOf(arg) > -1) break;
136                         add_files.push(arg);
137                         break;
138                     
139                     case 'rm':
140                         remove_files.push(arg);
141                         break;
142                     
143                     case 'commit' :
144                         messages.push(arg.message);
145                         break;    
146                 } 
147             });
148             //repo.debug = 1;
149             // these can fail... at present... as we wildcard stuff.
150             repo.add(add_files); 
151             repo.remove(remove_files);
152             
153             try { 
154                 success.push(repo.commit({
155                     reason : messages.join("\n"),
156                     files : add_files  
157                 }));
158                 success.push(repo.push());
159
160             } catch(e) {
161                 failure.push(e.message);
162                 
163             }   
164         }
165         
166         // finally merge all the commit messages.
167          
168         try {
169             // catch notification failures.. so we can carry on..
170             if (success.length) {
171                 print(success.join("\n"));
172                 
173                 var notification = new Notify.Notification({
174                     summary: "Git Live Commited",
175                     body : success.join("\n"),
176                     timeout : 5
177                     
178                 });
179     
180                 notification.set_timeout(5);
181                 notification.show();   
182             }
183             
184             if (failure.length) {
185             
186                 var notification = new Notify.Notification({
187                     summary: "Git Live ERROR!!",
188                     body : failure.join("\n"),
189                     timeout : 5
190                     
191                 });
192     
193                 notification.set_timeout(5); // show errros for longer
194                 notification.show();   
195             }
196         } catch(e) {
197             print(e.toString());
198             
199         }
200         this.queueRunning = false;
201     },
202     
203     shouldIgnore: function(f)
204     {
205         
206         if (this.paused) {
207             return true;
208         }
209         if (f.name[0] == '.') {
210             // except!
211             if (f.name == '.htaccess') {
212                 return false;
213             }
214             
215             return true;
216         }
217         if (f.name.match(/~$/)) {
218             return true;
219         }
220         // ignore anything in top level!!!!
221         if (!f.vpath.length) {
222             return true;
223         }
224         
225         return false;
226     },
227     
228     /**
229      * parsePath:
230      * Fill in gitlive, vpath and repo  
231      * 
232      */
233     parsePath: function(f)
234     {
235            
236         var vpath_ar = f.path.substring(this.gitlive.length +1).split('/');
237         
238         f.gitpath = this.gitlive + '/' + vpath_ar.shift();
239         f.vpath =  vpath_ar.join('/');
240         //f.repo = new imports.Scm.Git.Repo({ repopath: f.gitpath })
241         
242         
243     },
244     
245     just_created : {},
246       
247     onChanged : function(src) 
248     { 
249         return; // always ignore this..?
250         //this.parsePath(src);
251     },
252     
253     
254     
255     
256     /**
257      *  results in  git add  + git commit..
258      *
259      */
260     onChangesDoneHint : function(src) 
261     { 
262         this.parsePath(src);
263         if (this.shouldIgnore(src)) {
264             return;
265         }
266         
267        
268         var add_it = false;
269         if (typeof(this.just_created[src.path]) !='undefined') {
270             delete this.just_created[src.path];
271             this.lastAdd = new Date();
272             this.queue.push( 
273                 [ src.gitpath,  'add', src.vpath ],
274                 [ src.gitpath,  'commit',    { message: src.vpath} ] 
275                 
276             );
277          
278             return;
279         }
280         this.lastAdd = new Date();
281         this.queue.push( 
282             [ src.gitpath,  'add', src.vpath ],
283             [ src.gitpath,  'commit',  {  message: src.vpath} ]
284
285             
286         );
287     },
288     onDeleted : function(src) 
289     { 
290         this.parsePath(src);
291         if (this.shouldIgnore(src)) {
292             return;
293         }
294         // should check if monitor needs removing..
295         // it should also check if it was a directory.. - so we dont have to commit all..
296         
297         this.lastAdd = new Date();
298         this.queue.push( 
299             [ src.gitpath, 'rm' , src.vpath ],
300             [ src.gitpath, 'commit', { all: true, message: src.vpath} ]
301             
302         );
303     
304         
305     },
306     onCreated : function(src) 
307     { 
308         this.parsePath(src);
309         if (this.shouldIgnore(src)) {
310             return;
311         }
312         
313         if (!GLib.file_test(src.path, GLib.FileTest.IS_DIR)) {
314             this.just_created[src.path] = true;
315             return; // we do not handle file create flags... - use done hint.
316         }
317         // director has bee created
318         this.monitor(src.path);
319         this.lastAdd = new Date();
320         this.queue.push( 
321             [ src.gitpath, 'add' , src.vpath,  { all: true } ],
322             [ src.gitpath, 'commit' , { all: true, message: src.vpath} ]
323             
324         );
325         
326         
327     },
328     onAttributeChanged : function(src) { 
329         this.parsePath(src);
330         if (this.shouldIgnore(src)) {
331             return;
332         }
333         this.lastAdd = new Date();
334         this.queue.push(
335                         
336             //[ src.gitpath, 'commit' ,  src.vpath, { message: src.vpath} ]
337             [ src.gitpath, 'add' ,  src.vpath ],
338              [ src.gitpath, 'commit' ,    {  message: "Attribute Changed :" + src.vpath} ]
339         );
340  
341     
342     },
343     
344     onMoved : function(src,dest)
345     { 
346         this.parsePath(src);
347         this.parsePath(dest);
348         
349         if (src.gitpath != dest.gitpath) {
350             this.onDeleted(src);
351             this.onCreated(dest);
352             this.onChangedDoneHint(dest);
353             return;
354         }
355         // needs to handle move to/from unsupported types..
356         
357         if (this.shouldIgnore(src)) {
358             return;
359         }
360         if (this.shouldIgnore(dest)) {
361             return;
362         }
363         this.lastAdd = new Date();
364         this.queue.push( 
365            // [ src.gitpath, 'mv',  '-k', src.vpath, dest.vpath ],
366              [ src.gitpath, 'add',    dest.vpath ],
367              [ src.gitpath, 'rm',    src.vpath ],
368              
369             [ src.gitpath, 'commit' , 
370                 { message:   'MOVED ' + src.vpath +' to ' + dest.vpath}
371             ]
372         );
373          
374     }
375           
376     
377 });
378  
379