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