install1.2.sh
[gitlive] / gitlive.js
1 #!/usr/bin/seed
2 ///<script type="text/javascript">
3 /**
4 * Git Live
5
6 * inotify hooks for ~/gitlive
7 * that commit and push any changes made.
8 * Bit like a revision controled backed up file system!?
9
10
11 */
12
13
14  
15 GI = imports.gi.GIRepository;
16 GLib        = imports.gi.GLib;
17
18 // we add this in, as it appears to get lost sometimes if we set it using the ENV. variable in builder.sh
19 GI.Repository.prepend_search_path(GLib.get_home_dir() + '/.Builder/girepository-1.2');
20
21
22 var Gio      = imports.gi.Gio;
23 var Gtk      = imports.gi.Gtk;
24 var Notify = imports.gi.Notify;
25
26 var Spawn = imports.Spawn;
27 var Git = imports.Git;
28 var StatusIcon = imports.StatusIcon.StatusIcon;
29 var Monitor = imports.Monitor.Monitor;
30
31
32 //File = imports[__script_path__+'/../introspection-doc-generator/File.js'].File
33 Gtk.init (null, null);
34
35 var gitlive = GLib.get_home_dir() + "/gitlive";
36
37 if (!GLib.file_test(gitlive, GLib.FileTest.IS_DIR)) {
38     var msg = new Gtk.MessageDialog({message_type:
39         Gtk.MessageType.INFO, buttons : Gtk.ButtonsType.OK, text: "GIT Live - ~/gitlive does not exist."});
40     msg.run();
41     msg.destroy();
42     
43     Seed.quit();
44 }
45
46  
47 var monitor = new Monitor({
48     
49     queue : [],
50     queueRunning : false,
51      
52     start: function() {
53         var _this = this;
54         this.lastAdd = new Date();
55          
56         GLib.timeout_add(GLib.PRIORITY_LOW, 500, function() {
57             //TIMEOUT", _this.queue.length , _this.queueRunning].join(', '));
58             if (!_this.queue.length || _this.queueRunning) {
59                 return 1;
60             }
61             var last = Math.floor(((new Date()) - this.lastAdd) / 100);
62             if (last < 4) { // wait 1/2 a seconnd before running.
63                 return 1;
64             }
65             _this.runQueue();
66             return 1;
67         },null,null);
68         
69         Monitor.prototype.start.call(this);
70         var notification = new Notify.Notification({
71             summary: "Git Live",
72             body : gitlive + "\nMonitoring " + this.monitors.length + " Directories"
73         });
74
75         notification.set_timeout(2000);
76         notification.show();   
77     },
78     /**
79      * run the queue.
80      * - pulls the items off the queue 
81      *    (as commands run concurrently and new items may get added while it's running)
82      * - runs the queue items
83      * - pushes upstream.
84      * 
85      */
86     runQueue: function()
87     {
88         this.queueRunning = true;
89         var cmds = [];
90         this.queue.forEach(function (q) {
91             cmds.push(q);
92         });
93         this.queue = []; // empty queue!
94         
95         var success = [];
96         var failure = [];
97         var repos = [];
98         var done = [];
99         cmds.forEach(function(cmd) {
100             // prevent duplicate calls..
101             if (done.indexOf(cmd.join(',')) > -1) {
102                 return;
103             }
104             done.push(cmd.join(','));
105             
106             if (repos.indexOf(cmd[0]) < 0) {
107                 repos.push(cmd[0]);
108                 Git.run(cmd[0] , 'pull'); // pull before we push!
109             }
110             var sp = Git.run.apply(Git,cmd);
111              
112             switch (sp.result * 1) {
113                 case 0: // success:
114                     success.push(sp.args.join(' '));
115                     if (sp.output.length) success.push(sp.output + '');
116                   // if (sp.stderr.length) success.push(sp.stderr + '');
117                     break;
118                 default: 
119                     failure.push(sp.args.join(' '));
120                     if (sp.output.length) failure.push(sp.output);
121                     if (sp.stderr.length) failure.push(sp.stderr);
122                     break;
123             }
124             
125         });
126          
127         // push upstream.
128         repos.forEach(function(r) {
129             var sp = Git.run(r , 'push', { all: true } );
130             if (sp.length) {
131                 success.push(sp);
132             }
133             
134         });
135         
136         if (success.length) {
137             print(success.join("\n"));
138             var notification = new Notify.Notification({
139                 summary: "Git Live Commited",
140                 body : success.join("\n")
141                 
142             });
143
144             notification.set_timeout(2000);
145             notification.show();   
146         }
147         if (failure.length) {
148         
149             var notification = new Notify.Notification({
150                 summary: "Git Live ERROR!!",
151                 body : failure.join("\n")
152                 
153             });
154
155             notification.set_timeout(5000); // show errros for longer
156             notification.show();   
157         }
158         this.queueRunning = false;
159     },
160     
161     shouldIgnore: function(f)
162     {
163         if (f.name[0] == '.') {
164             // except!
165             if (f.name == '.htaccess') {
166                 return false;
167             }
168             
169             return true;
170         }
171         if (f.name.match(/~$/)) {
172             return true;
173         }
174         // ignore anything in top level!!!!
175         if (!f.vpath.length) {
176             return true;
177         }
178         
179         return false;
180         
181     },
182     
183     parsePath: function(f) {
184            
185         var vpath_ar = f.path.substring(gitlive.length +1).split('/');
186         
187         f.gitpath = gitlive + '/' + vpath_ar.shift();
188         f.vpath =  vpath_ar.join('/');
189         
190         
191     },
192     
193     just_created : {},
194       
195     onChanged : function(src) 
196     { 
197         return; // always ignore this..?
198         //this.parsePath(src);
199     },
200     onChangesDoneHint : function(src) 
201     { 
202         this.parsePath(src);
203         if (this.shouldIgnore(src)) {
204             return;
205         }
206         
207         var add_it = false;
208         if (typeof(this.just_created[src.path]) !='undefined') {
209             delete this.just_created[src.path];
210             this.lastAdd = new Date();
211             this.queue.push( 
212                 [ src.gitpath,  'add', src.vpath ],
213                 [ src.gitpath,  'commit',  src.vpath, { message: src.vpath} ] 
214                 
215             );
216          
217             return;
218         }
219         this.lastAdd = new Date();
220         this.queue.push( 
221             [ src.gitpath,  'add', src.vpath ],
222             [ src.gitpath,  'commit', src.vpath, {  message: src.vpath} ]
223
224             
225         );
226        
227
228     },
229     onDeleted : function(src) 
230     { 
231         this.parsePath(src);
232         if (this.shouldIgnore(src)) {
233             return;
234         }
235         // should check if monitor needs removing..
236         // it should also check if it was a directory.. - so we dont have to commit all..
237         
238         this.lastAdd = new Date();
239         this.queue.push( 
240             [ src.gitpath, 'rm' , src.vpath ],
241             [ src.gitpath, 'commit', { all: true, message: src.vpath} ]
242             
243         );
244     
245         
246     },
247     onCreated : function(src) 
248     { 
249         this.parsePath(src);
250         if (this.shouldIgnore(src)) {
251             return;
252         }
253         
254         if (!GLib.file_test(src.path, GLib.FileTest.IS_DIR)) {
255             this.just_created[src.path] = true;
256             return; // we do not handle file create flags... - use done hint.
257         }
258         // director has bee created
259         this.monitor(src.path);
260         this.lastAdd = new Date();
261         this.queue.push( 
262             [ src.gitpath, 'add' , src.vpath,  { all: true } ],
263             [ src.gitpath, 'commit' , { all: true, message: src.vpath} ]
264             
265         );
266         
267         
268     },
269     onAttributeChanged : function(src) { 
270         this.parsePath(src);
271         if (this.shouldIgnore(src)) {
272             return;
273         }
274         this.lastAdd = new Date();
275         this.queue.push( 
276             [ src.gitpath, 'commit' ,  src.vpath, { message: src.vpath} ]
277         );
278  
279     
280     },
281     
282     onMoved : function(src,dest)
283     { 
284         this.parsePath(src);
285         this.parsePath(dest);
286         
287         if (src.gitpath != dest.gitpath) {
288             this.onDeleted(src);
289             this.onCreated(dest);
290             this.onChangedDoneHint(dest);
291             return;
292         }
293         // needs to handle move to/from unsupported types..
294         
295         if (this.shouldIgnore(src)) {
296             return;
297         }
298         if (this.shouldIgnore(dest)) {
299             return;
300         }
301         this.lastAdd = new Date();
302         this.queue.push( 
303             [ src.gitpath, 'mv',  '-k', src.vpath, dest.vpath ],
304             [ src.gitpath, 'commit' ,  src.vpath, dest.vpath ,
305                 { message:   'MOVED ' + src.vpath +' to ' + dest.vpath} ]
306         );
307          
308     }
309           
310     
311 });
312  
313  
314   
315
316 function errorDialog(data) {
317     var msg = new Gtk.MessageDialog({
318             message_type: Gtk.MessageType.ERROR, 
319             buttons : Gtk.ButtonsType.OK, 
320             text: data
321     });
322     msg.run();
323     msg.destroy();
324 }
325
326  
327
328
329
330 //
331 // need a better icon...
332
333
334 StatusIcon.init();   
335
336
337 Notify.init("gitlive");
338
339 monitor.add(GLib.get_home_dir() + "/gitlive");
340 monitor.start();
341 Gtk.main();
342 //icon.signal["activate"].connect(on_left_click);
343