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