GitMonitor.js
[gitlive] / Monitor.js
1 //<Script type="text/javascript">
2 var Gio     = imports.gi.Gio;
3 var GLib    = imports.gi.GLib;
4
5 var XObject = imports.XObject.XObject;
6 var File    = imports.File.File;
7
8 /**
9  * Monitor class - handles monitor managment for a large tree...
10  *
11  *
12  * This 
13  * 
14  * usage : 
15  * x = new Monitor({
16      change : function () {
17          * ....
18          *}
19   }
20  * x.add('/somepath')
21  * x.stop() // stops all scanning.
22  * x.play(); // starts the scanning
23  * 
24  * 
25  * 
26  * 
27  */
28  
29 function Monitor(cfg){
30     for (var i in cfg) {
31         this[i] = cfg[i];
32     }
33     
34     
35     this.monitors = [];
36     
37     this.top = [];
38     
39 }
40
41 Monitor.prototype = {
42     
43     monitors : false, // Array of GioFileMonitors
44     top : false, // list of top level directories..
45     paused : false,
46     /**
47      * add a directory or file to monitor
48      */
49     add : function(add)
50     {
51         this.top.push(add);
52     },
53     /**
54      * start monitoring
55      */
56     start : function()
57     {
58         for(var i =0;i < this.top.length; i++) {
59             this.monitor(this.top[i]);
60         }
61     },
62     /**
63      * stop / pause monitoring
64      * 
65      */
66     stop : function()
67     {
68         
69         for(var i =0;i < this.monitors.length; i++) {
70             this.monitors[i].cancel();
71         } 
72         this.monitors = [];
73     },
74     /**
75      * pause monitoring - without changing what's monitored 
76      */
77     pause : function()
78     {
79         this.paused = true;
80     },
81     /**
82      * resume monitoring - without changing what's monitored 
83      */
84     resume : function()
85     {
86         this.paused = false;
87     },
88     /**
89      * monitor a file or directory (privatish)
90      *
91      * initially called with ~/gitlive  null 0 (effectvely)
92      * 
93      * 
94      */
95     monitor : function(path, fn, depth)
96     {
97         var _this = this;
98         
99        // print("ADD: " + path)
100         
101         depth = typeof(depth) == 'number'  ? depth *1 : 0;
102         
103         
104         fn = fn || function (fm, f, of, event_type, uh) {
105             _this.onEvent(fm, f, of, event_type, uh);
106         }
107        
108           
109         var f = Gio.file_new_for_path(path);
110             //var cancel = new Gio.Cancellable ();
111         if (depth > 0) {     
112             var fm = f.monitor(2,null); //Gio.FileMonitorFlags.SEND_MOVED
113             
114             XObject.isSeed ?  fm.signal.changed.connect(fn) : fm.connect('changed',fn);
115             this.monitors.push(fm);
116             // print("ADD path " + depth + ' ' + path);
117         }
118         // iterate children?
119         // - this is not used.
120         //if (GLib.file_test(path + '/.git' , GLib.FileTest.IS_DIR) && this.initRepo) {
121             
122         //    this.initRepo(path);
123         //}
124         
125          var file_enum = f.enumerate_children(
126             Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ','+ 
127             Gio.FILE_ATTRIBUTE_STANDARD_TYPE,
128             Gio.FileQueryInfoFlags.NONE,
129             null);
130         
131         var next_file;
132         
133         while ((next_file = file_enum.next_file(null)) != null) {
134          
135             //print("got a file " + next_file.sudo () + '?=' + Gio.FileType.DIRECTORY);
136             
137             if (next_file.get_file_type() != Gio.FileType.DIRECTORY) {
138                 next_file = null;
139                 continue;
140             }
141             
142             if (next_file.get_file_type() == Gio.FileType.SYMBOLIC_LINK) {
143                 next_file = null;
144                 continue;
145             }
146             
147             if (next_file.get_display_name()[0] == '.') {
148                 next_file = null;
149                 continue;
150             }
151             var sp = path+'/'+next_file.get_display_name();
152             // skip modules.
153             //print("got a file : " + sp);
154          
155             next_file = null;
156             
157             
158             
159             this.monitor(sp, fn, depth + 1);
160             
161         }
162     
163         file_enum.close(null);
164     },
165     
166     
167     
168     realpath : function(file)
169     {
170         if (!file) {
171             return file;
172         }
173         
174         if (GLib.file_test(file.get_path(), GLib.FileTest.EXISTS)) {
175             var rp = File.realpath(file.get_path());
176             return Gio.file_new_for_path(rp);  
177             
178         }
179         // file does not currently exist..
180         // check parent.
181         var bn = file.get_basename();
182         var ar = file.get_path().split('/');
183         ar.pop();
184         var dirname = ar.join('/');
185         var rp = File.realpath(dirname);
186         return Gio.file_new_for_path(rp + '/' + bn);
187         
188     },
189    
190     
191     
192     
193     
194     onEvent : function(fm, f_orig, of_orig, event_type, uh)
195     {
196         if (this.paused) {
197             return;
198         }
199         
200         var f = this.realpath(f_orig);
201         
202         var of = this.realpath(of_orig);
203  
204         var src = {
205             name : f.get_basename(),
206             path : f.get_path(),
207             dir   : GLib.path_get_dirname(f.get_path())
208         };
209         
210         var dest = false;
211         
212         if (of) {
213             
214             dest =  {
215                 name : of.get_basename(),
216                 path : of.get_path(),
217                 dir   : GLib.path_get_dirname(of.get_path())
218             }
219         }
220         var event_name = 'UKNOWN';;
221         
222         for(var i in Gio.FileMonitorEvent) {
223             if (Gio.FileMonitorEvent[i] == event_type) {
224                 event_name = i;
225             }
226         }
227         
228         //print (JSON.stringify([event_name , f.get_path(), of ? of.get_path() : false ] ));
229         //print ("got src: " + src.toString());
230         //print ("got event: " + src.toString());
231         try {
232                 
233             switch(event_type) {
234                 case Gio.FileMonitorEvent.CHANGED:
235                     this.onChanged(src);
236                     return; // ingore thise?? -wait for changes_done_htin?
237                     
238                 case Gio.FileMonitorEvent.CHANGES_DONE_HINT:
239                     this.onChangesDoneHint(src);
240                     return;
241                     
242                 case Gio.FileMonitorEvent.DELETED:
243                     this.onDeleted(src);
244                     return;
245                     
246                 case Gio.FileMonitorEvent.CREATED:
247                     this.onCreated(src);
248                     return;
249                 
250                 case Gio.FileMonitorEvent.ATTRIBUTE_CHANGED: // eg. chmod/chatt
251                     this.onAttributeChanged(src);
252                     return;
253                 
254                 case Gio.FileMonitorEvent.MOVED: // eg. chmod/chatt
255                     this.onMoved(src,dest);
256                     return; 
257                 
258                 // rest are mount related - not really relivant.. maybe add later..
259             } 
260         } catch(e) {
261             print(e);
262         }
263         
264     },
265     
266     /** override these to do stuff.. */
267     initRepo : function(src) { }, // called on startup at the top level repo dir.
268     onChanged : function(src) { },
269     onChangesDoneHint : function(src) { },
270     onDeleted : function(src) { },
271     onCreated : function(src) { },
272     onAttributeChanged : function(src) { },
273     onMoved : function(src) { }
274           
275     
276 }
277  
278  
279
280
281
282
283