Monitor.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.montors.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         
126         var file_enum = f.enumerate_children(
127             Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ','+ 
128             Gio.FILE_ATTRIBUTE_STANDARD_TYPE,
129             Gio.FileQueryInfoFlags.NONE,
130             null);
131         
132        var next_file;
133         
134         while ((next_file = file_enum.next_file(null)) != null) {
135          
136             if (next_file.get_file_type() != Gio.FileType.DIRECTORY) {
137                 next_file = null;
138                 continue;
139             }
140             
141             if (next_file.get_file_type() == Gio.FileType.SYMBOLIC_LINK) {
142                 next_file = null;
143                 continue;
144             }
145             
146             if (next_file.get_display_name()[0] == '.') {
147                 next_file = null;
148                 continue;
149             }
150             var sp = path+'/'+next_file.get_display_name();
151             // skip modules.
152            
153             next_file = null;
154             this.monitor(sp, fn, depth + 1);
155             
156         }
157     
158         file_enum.close(null);
159     },
160     
161     
162     
163     realpath : function(file)
164     {
165         if (!file) {
166             return file;
167         }
168         
169         if (GLib.file_test(file.get_path(), GLib.FileTest.EXISTS)) {
170             var rp = File.realpath(file.get_path());
171             return Gio.file_new_for_path(rp);  
172             
173         }
174         // file does not currently exist..
175         // check parent.
176         var bn = file.get_basename();
177         var ar = file.get_path().split('/');
178         ar.pop();
179         var dirname = ar.join('/');
180         var rp = File.realpath(dirname);
181         return Gio.file_new_for_path(rp + '/' + bn);
182         
183     },
184    
185     
186     
187     
188     
189     onEvent : function(fm, f_orig, of_orig, event_type, uh)
190     {
191         if (this.paused) {
192             return;
193         }
194         
195         var f = this.realpath(f_orig);
196         
197         var of = this.realpath(of_orig);
198  
199         var src = {
200             name : f.get_basename(),
201             path : f.get_path(),
202             dir   : GLib.path_get_dirname(f.get_path())
203         };
204         
205         var dest = false;
206         
207         if (of) {
208             
209             dest =  {
210                 name : of.get_basename(),
211                 path : of.get_path(),
212                 dir   : GLib.path_get_dirname(of.get_path())
213             }
214         }
215         var event_name = 'UKNOWN';;
216         
217         for(var i in Gio.FileMonitorEvent) {
218             if (Gio.FileMonitorEvent[i] == event_type) {
219                 event_name = i;
220             }
221         }
222         
223         //print (JSON.stringify([event_name , f.get_path(), of ? of.get_path() : false ] ));
224         //print ("got src: " + src.toString());
225         //print ("got event: " + src.toString());
226         try {
227                 
228             switch(event_type) {
229                 case Gio.FileMonitorEvent.CHANGED:
230                     this.onChanged(src);
231                     return; // ingore thise?? -wait for changes_done_htin?
232                     
233                 case Gio.FileMonitorEvent.CHANGES_DONE_HINT:
234                     this.onChangesDoneHint(src);
235                     return;
236                     
237                 case Gio.FileMonitorEvent.DELETED:
238                     this.onDeleted(src);
239                     return;
240                     
241                 case Gio.FileMonitorEvent.CREATED:
242                     this.onCreated(src);
243                     return;
244                 
245                 case Gio.FileMonitorEvent.ATTRIBUTE_CHANGED: // eg. chmod/chatt
246                     this.onAttributeChanged(src);
247                     return;
248                 
249                 case Gio.FileMonitorEvent.MOVED: // eg. chmod/chatt
250                     this.onMoved(src,dest);
251                     return; 
252                 
253                 // rest are mount related - not really relivant.. maybe add later..
254             } 
255         } catch(e) {
256             print(e);
257         }
258         
259     },
260     
261     /** override these to do stuff.. */
262     initRepo : function(src) { }, // called on startup at the top level repo dir.
263     onChanged : function(src) { },
264     onChangesDoneHint : function(src) { },
265     onDeleted : function(src) { },
266     onCreated : function(src) { },
267     onAttributeChanged : function(src) { },
268     onMoved : function(src) { }
269           
270     
271 }
272  
273  
274
275
276
277
278