Fix #5662 - Gitlive - create a tracking branch
[gitlive] / old_seed_version / 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 the monitoring
44      * and run the queue every 500 milliseconds..
45      *
46      */
47     start: function() {
48         imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_REFRESH );
49         var _this = this;
50         this.lastAdd = new Date();
51         
52         GLib.timeout_add(GLib.PRIORITY_LOW, 500, function() {
53             _this.top.forEach(_this.monitor, _this);
54             imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PLAY );
55             
56             try { 
57                 var notification = new Notify.Notification({
58                     summary: "Git Live",
59                     body : this.gitlive + "\nMonitoring " + _this.monitors.length + " Directories",
60                     timeout : 5
61                 });
62         
63                 notification.set_timeout(5);
64                 notification.show();
65             } catch(e) {
66                 print(e.toString());
67             }
68
69         });
70         
71         GLib.timeout_add(GLib.PRIORITY_LOW, 1000, function() {
72             //TIMEOUT", _this.queue.length , _this.queueRunning].join(', '));
73             if (!_this.queue.length || _this.queueRunning) {
74                 return 1;
75             }
76             var last = Math.floor(((new Date()) - _this.lastAdd) / 100);
77             
78             //print("LAST RUN?" + last);
79             
80             if (last < 5) { // wait 1/2 a seconnd before running.
81                 return 1;
82             }
83             //_this.lastAdd = new Date();
84             //return 1;
85         
86             _this.runQueue();
87             return 1;
88         },null,null);
89         
90       
91     },
92     
93     
94     stop: function() {
95         imports.StatusIcon.StatusIcon.el.set_from_stock( Gtk.STOCK_MEDIA_PAUSE );
96         Monitor.prototype.stop.call(this);
97     },
98     
99     
100     monitor : function(path, fn, depth)
101     {
102         depth = typeof(depth) == 'number'  ? depth *1 : 0;
103         
104          
105         // if we are not at top level.. and there is a .git directory  (it's a submodule .. ignore) 
106         if (depth > 1 && GLib.file_test(path + '/.git' , GLib.FileTest.IS_DIR)) {
107             return;
108         }
109         
110         if (depth == 1) {
111             var repo = imports.Scm.Repo.Repo.get(path);
112             if (!repo || !repo.autocommit()) {
113                 return;
114             } 
115         }
116         
117         
118         // check if the repo is to be monitored.
119         //print("PATH : " + path);
120         
121         
122         Monitor.prototype.monitor.call(this, path,fn, depth);
123     },
124     
125     /**
126      * run the queue.
127      * - pulls the items off the queue 
128      *    (as commands run concurrently and new items may get added while it's running)
129      * - runs the queue items
130      * - pushes upstream.
131      * 
132      */
133     runQueue: function()
134     {
135         
136         if (this.paused) {
137             return;
138         }
139         this.queueRunning = true;
140         var cmds = [];
141         this.queue.forEach(function (q) {
142             cmds.push(q);
143         });
144         this.queue = []; // empty queue!
145         
146         var success = [];
147         var failure = [];
148         var repos = [];
149         var done = [];
150         
151         // first build a array of repo's to work with
152         var repo_list = {};
153         
154         // pull and group.
155         
156         //print(JSON.stringify(cmds));
157         this.paused = true;
158         cmds.forEach(function(cmd) {
159             var gitpath = cmd.shift(); 
160             if (typeof(repo_list[gitpath]) == 'undefined') {
161                 repo_list[gitpath] = new imports.Scm.Git.Repo.Repo( { repopath : gitpath });
162                 repo_list[gitpath].cmds = [];
163                 repo_list[gitpath].pull();
164             }
165             repo_list[gitpath].cmds.push(cmd);
166         });
167         this.paused = false;
168         // build add, remove and commit message list..
169         
170          
171          
172         for (var gitpath in repo_list) {
173             var repo = repo_list[gitpath];
174             var add_files = [];
175             var remove_files = [];
176             var messages = [];
177             //print(JSON.stringify(repo.cmds,null,4));
178             
179             repo.cmds.forEach(function(cmd) {
180                 
181                 var name = cmd.shift();
182                 var arg = cmd.shift();
183                 
184                 switch(name) {
185                     case 'add' :
186                         
187                         if (add_files.indexOf(arg) > -1) {
188                             break;
189                         }
190                         
191                         // if file does not exist.. s,ip
192                         
193                         //if (!GLib.file_test(arg, GLib.FileTest.EXISTS)) {
194                              
195                         //    break;
196                          // }
197         
198                         
199                         add_files.push(arg);
200                         break;
201                     
202                     case 'rm':
203                         
204                         if (add_files.indexOf(arg) > -1) {
205                             break;
206                         }
207                         
208                         // if file exists, do not try and delete it.
209                         if (GLib.file_test(arg, GLib.FileTest.EXISTS)) {
210                             break;
211                         }
212                         
213                         remove_files.push(arg);
214                         break;
215                     
216                     case 'commit' :
217                         
218                         if (messages.indexOf(arg.message) < 0) { 
219                             messages.push(arg.message);
220                         }
221                         break;    
222                 } 
223             });
224             
225             //repo.debug = 1;
226             // these can fail... at present... as we wildcard stuff.
227             print("ADD : "  + JSON.stringify(add_files));
228             
229             // make sure added files do not get removed..
230             remove_files  = remove_files.filter(function(v) {
231                 return add_files.indexOf(v) < 0;
232             });
233             print("REMOVE : "  + JSON.stringify(remove_files));
234             
235             
236             // make sure monitoring is paused so it does not recursively pick up
237             // deletions
238             
239             // -- DO STUFF..
240             
241             repo.add(add_files);
242             
243             repo.remove(remove_files);
244             this.paused = false;
245             
246             
247             try { 
248                 success.push(repo.commit({
249                     reason : messages.join("\n"),
250                     files : add_files  
251                 }));
252                 success.push(repo.push());
253
254             } catch(e) {
255                 failure.push(e.message);
256                 
257             }   
258         }
259         
260         // finally merge all the commit messages.
261          
262         try {
263             // catch notification failures.. so we can carry on..
264             if (success.length) {
265                 print(success.join("\n"));
266                 
267                 var notification = new Notify.Notification({
268                     summary: "Git Live Commited",
269                     body : success.join("\n"),
270                     timeout : 5
271                     
272                 });
273     
274                 notification.set_timeout(5);
275                 notification.show();   
276             }
277             
278             if (failure.length) {
279             
280                 var notification = new Notify.Notification({
281                     summary: "Git Live ERROR!!",
282                     body : failure.join("\n"),
283                     timeout : 5
284                     
285                 });
286     
287                 notification.set_timeout(5); // show errros for longer
288                 notification.show();   
289             }
290         } catch(e) {
291             print(e.toString());
292             
293         }
294         this.queueRunning = false;
295     },
296     
297     shouldIgnore: function(f)
298     {
299         
300         if (this.paused) {
301             return true;
302         }
303         
304         
305         // vim.. what a seriously brain dead program..
306         if (f.name == '4913') {
307             return true;
308         }
309         
310         if (f.name[0] == '.') {
311             // except!
312             if (f.name == '.htaccess') {
313                 return false;
314             }
315             
316             return true;
317         }
318         if (f.name.match(/~$/)) {
319             return true;
320         }
321         if (f.name.match(/^nbproject/)) {
322             return true;
323         }
324         // ignore anything in top level!!!!
325         if (!f.vpath.length) {
326             return true;
327         }
328         
329         return false;
330     },
331     
332     /**
333      * parsePath:
334      * Fill in gitlive, vpath and repo  
335      * 
336      */
337     parsePath: function(f)
338     {
339            
340         var vpath_ar = f.path.substring(this.gitlive.length +1).split('/');
341         
342         f.gitpath = this.gitlive + '/' + vpath_ar.shift();
343         f.vpath =  vpath_ar.join('/');
344         //f.repo = new imports.Scm.Git.Repo({ repopath: f.gitpath })
345         
346         
347     },
348     
349     just_created : {},
350       
351     onChanged : function(src) 
352     { 
353         return; // always ignore this..?
354         //this.parsePath(src);
355     },
356     
357     
358     
359     
360     /**
361      *  results in  git add  + git commit..
362      *
363      */
364     onChangesDoneHint : function(src) 
365     { 
366         this.lastAdd = new Date();
367         this.parsePath(src);
368         if (this.shouldIgnore(src)) {
369             return;
370         }
371         
372        
373         var add_it = false;
374         if (typeof(this.just_created[src.path]) !='undefined') {
375             delete this.just_created[src.path];
376             
377             this.queue.push( 
378                 [ src.gitpath,  'add', src.vpath ],
379                 [ src.gitpath,  'commit',    { message: src.vpath} ] 
380                 
381             );
382          
383             return;
384         }
385         
386         this.queue.push( 
387             [ src.gitpath,  'add', src.vpath ],
388             [ src.gitpath,  'commit',  {  message: src.vpath} ]
389
390             
391         );
392     },
393     onDeleted : function(src) 
394     { 
395         this.lastAdd = new Date();
396         this.parsePath(src);
397         if (this.shouldIgnore(src)) {
398             return;
399         }
400         // should check if monitor needs removing..
401         // it should also check if it was a directory.. - so we dont have to commit all..
402         
403         
404         this.queue.push( 
405             [ src.gitpath, 'rm' , src.vpath ],
406             [ src.gitpath, 'commit', { all: true, message: src.vpath} ]
407             
408         );
409     
410         
411     },
412     onCreated : function(src) 
413     { 
414         this.lastAdd = new Date();
415         this.parsePath(src);
416         if (this.shouldIgnore(src)) {
417             return;
418         }
419         
420         if (!GLib.file_test(src.path, GLib.FileTest.IS_DIR)) {
421             this.just_created[src.path] = true;
422             return; // we do not handle file create flags... - use done hint.
423         }
424         // director has bee created
425         this.monitor(src.path);
426         
427         this.queue.push( 
428             [ src.gitpath, 'add' , src.vpath,  { all: true } ],
429             [ src.gitpath, 'commit' , { all: true, message: src.vpath} ]
430             
431         );
432         
433         
434     },
435     onAttributeChanged : function(src)
436     { 
437         this.lastAdd = new Date();
438         this.parsePath(src);
439         if (this.shouldIgnore(src)) {
440             return;
441         }
442         
443         this.queue.push(
444                         
445             //[ src.gitpath, 'commit' ,  src.vpath, { message: src.vpath} ]
446             [ src.gitpath, 'add' ,  src.vpath ],
447              [ src.gitpath, 'commit' ,    {  message: "Attribute Changed :" + src.vpath} ]
448         );
449  
450     
451     },
452     
453     onMoved : function(src,dest)
454     { 
455         this.lastAdd = new Date();
456         this.parsePath(src);
457         this.parsePath(dest);
458         
459         if (src.gitpath != dest.gitpath) {
460             this.onDeleted(src);
461             this.onCreated(dest);
462             this.onChangedDoneHint(dest);
463             return;
464         }
465         // needs to handle move to/from unsupported types..
466         
467         if (this.shouldIgnore(src)) {
468             return;
469         }
470         if (this.shouldIgnore(dest)) {
471             return;
472         }
473         
474         this.queue.push( 
475            // [ src.gitpath, 'mv',  '-k', src.vpath, dest.vpath ],
476              [ src.gitpath, 'add',    dest.vpath ],
477              [ src.gitpath, 'rm',    src.vpath ],
478              
479             [ src.gitpath, 'commit' , 
480                 { message:   'MOVED ' + src.vpath +' to ' + dest.vpath}
481             ]
482         );
483          
484     }
485           
486     
487 });
488  
489