File.js
[app.jsdoc] / File.js
1 // <script type ="text/Javascript">
2 GLib = imports.gi.GLib;
3 Gio = imports.gi.Gio;
4
5 String  = imports.String.String; 
6 /**
7 * @class File
8 * @singleton
9
10 * Library to wrap GLib and Gio basic File related methods
11
12 * usage:
13
14 * File = import.File.File;
15
16 * var contents = File.read("/tmp/test.txt");
17 *
18
19
20 */
21 var File = {
22     
23     /**
24      * @scope File
25      */
26      
27     
28     SEPARATOR : '/',
29
30  // fixme - this needs a bitter location.. 
31     // they where in a string class before, but  overriding String methods is not a good normally a good idea..
32       
33     /**
34      * Right trim (in here to reduce dependancies)
35      * @param {String} s the string to trim
36      * @param {String} string to trim off right..
37      * @return {String} the trimmed string
38      */
39     rtrim : function (s,toTrim) {
40         if (s.substr(s.length - toTrim.length) == toTrim) {
41             return s.slice(0, s.length - toTrim.length);
42         }
43    
44         return s;
45     },
46     /**
47      * Trim a string (in here to reduce dependancies)
48      * @param {String} s the string to trim
49      * @param {String} string to trim off right..
50      * @return {String} the trimmed string
51      */
52     trim : function (s,toTrim) {
53         var out = this.ltrim(s,toTrim);
54         out = this.rtrim(out,toTrim);
55         return out;
56     },
57     /**
58      * Left Trim a string (in here to reduce dependancies)
59      * @param {String} s the string to trim
60      * @param {String} string to trim off right..
61      * @return {String} the trimmed string
62      */
63     ltrim : function (s, toTrim) {
64         if (s.substr(0, toTrim.length) == toTrim) {
65             return s.slice(toTrim.length);
66         }
67         
68         return s;
69     },
70     /**
71      * Join a path with the Correct File seperator (unix only at present...)
72      * Takes a variable number of arguments, and joins them together.
73      * @return {String} the joined path
74      */
75     join : function () {
76         var out = "";
77         for (var i = 0; i < arguments.length; i++) {
78             if (i == 0) {
79               out += this.rtrim(arguments[i], File.SEPARATOR);
80             }
81             else if (i == arguments.length - 1) {
82               out += File.SEPARATOR + this.ltrim(arguments[i], File.SEPARATOR);
83             }
84             else {
85               out += File.SEPARATOR + this.trim(arguments[i], File.SEPARATOR);
86             }
87         }
88         return out;
89     }, 
90     read : function (path) {
91         var out = {};
92         GLib.file_get_contents(path, out, null, null);
93         return out['value'];
94     },
95
96     isFile : function (path) {
97       return GLib.file_test(path, GLib.FileTest.IS_REGULAR);
98     },
99     exists : function (path) {
100       return GLib.file_test(path, GLib.FileTest.EXISTS);
101     },
102     isDirectory : function (path) {
103       return GLib.file_test(path, GLib.FileTest.IS_DIR);
104     },
105
106     list : function (path) {
107         var listing = [];
108
109         var f = Gio.file_new_for_path(String(path));
110         var file_enum = f.enumerate_children(Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, Gio.FileQueryInfoFlags.NONE, null);
111
112         var next_file = null;
113
114         while ((next_file = file_enum.next_file(null)) != null) {
115           listing.push(next_file.get_display_name());
116         }
117
118         file_enum.close(null);
119
120         listing.sort();
121
122         return listing;
123     },
124
125     mtime : function (path) {
126         var f = Gio.file_new_for_path(String(path));
127         var mtime = new GLib.TimeVal();
128
129         var info = f.query_info(Gio.FILE_ATTRIBUTE_TIME_MODIFIED, Gio.FileQueryInfoFlags.NONE, null);
130         info.get_modification_time(mtime);
131
132         return new Date(mtime.tv_sec * 1000);
133     },
134
135     canonical : function (path) {
136         var f = Gio.file_new_for_path(String(path));
137         var can = f.resolve_relative_path('');
138         return can.get_path();
139     },
140     
141     /**
142      * write
143      * @arg path {String} File to write to
144      * @arg string {String} Contents of file.
145      * 
146      */
147     write : function (path, string) {
148         var f = Gio.file_new_for_path(String(path));
149         var data_out = new Gio.DataOutputStream({base_stream:f.replace(null, false, Gio.FileCreateFlags.NONE, null)});
150         data_out.put_string(string, null);
151         data_out.close(null);
152     },
153     /**
154      * append
155      * @arg path {String} File to write to
156      * @arg string {String} string to append to file.
157      * 
158      */
159     append : function (path, string) {
160         var f = Gio.file_new_for_path(String(path));
161         var data_out = new Gio.DataOutputStream({
162                 base_stream:f.append_to(Gio.FileCreateFlags.NONE, null)
163         });
164         data_out.put_string(string, null);
165         data_out.close(null);
166     },
167     /**
168      * remove 
169      * Delete a file.
170      * @arg path {String} File to remove
171      * 
172      * 
173      */
174     remove : function (path)
175     {
176         var f = Gio.file_new_for_path(String(path));
177         return f['delete']();
178     },
179     /**
180      * silentRecursiveCopy
181      * copy files recursively from fromDir, silently ignore them if they already exist in toDir
182      *        unless you select overwrite..
183      * @arg {String} src source path
184      * @arg {String} dest destination path
185      * @arg {Gio.FileCopyFlags} options (optional)  - use Gio.FileCopyFlags.OVERWRITE to 
186      *      otherwise they will not be copied
187      * 
188      */
189     silentRecursiveCopy : function (fromDir, toDir, opts) {
190         
191         var filesToCopy = File.recursiveListing(fromDir);
192         var srcPath, destPath, src, dest;
193         if (typeof(opts) =='undefined') {
194             opts = Gio.FileCopyFlags.NONE;
195         }
196         
197         for (var index in filesToCopy) {
198             srcPath = File.join(String(fromDir), filesToCopy[index]);
199             destPath = File.join(String(toDir), filesToCopy[index]);
200
201             if (File.isDirectory(srcPath) && !File.isDirectory(destPath)) {
202                 File.mkdir(destPath);
203                 continue;
204             }
205             // source is not file..?!?!?
206             if (!File.isFile(srcPath)) {
207                 continue;
208             }
209             if (File.isFile(destPath) && opts == Gio.FileCopyFlags.NONE) {
210                 // do not overwrite.. - if file exists and we are not flaged to overwrite.
211                 continue;
212             }
213             
214             File.copyFile(srcPath, destPath, opts);
215            
216         }
217     },
218     
219     /**
220      * mkdir
221      * make a directory..
222      * @arg {String} dstPath directory to make
223      */
224     mkdir : function (destPath) {
225         var dest = Gio.file_new_for_path(String(destPath));
226         
227         return dest.make_directory(null, null);
228     },
229     /**
230      * copyFile
231      * @arg {String} src source path
232      * @arg {String} dest destination path
233      * @arg {Gio.FileCopyFlags} options (optional)  - use Gio.FileCopyFlags.OVERWRITE to .. overwrite..
234      * 
235      */
236     copyFile : function (srcPath, destPath, opts) {
237         if (typeof(opts) =='undefined') {
238             opts = Gio.FileCopyFlags.NONE;
239         }
240         var dest = Gio.file_new_for_path(String(destPath));
241         var src = Gio.file_new_for_path(String(srcPath));
242
243         // a bit of a hack for the fact that Gio.File.copy arguments
244         // can be nulled, but not according to the GIR file
245         return src.copy(dest, opts);
246     },
247
248     recursiveListing : function (dir) {
249
250         function recursiveListingInternal(prefix, listing, dir) {
251           var entries = File.list(dir);
252           var next, fullPath;
253
254           for (var index in entries) {
255             next = entries[index];
256             fullPath = File.join(prefix, dir, next);
257
258             if (File.isDirectory(fullPath)) {
259               listing.push(next);
260               listing = listing.concat(recursiveListingInternal(next, [], fullPath));
261             }
262             else {
263               if (prefix) {
264                 next = File.join(prefix, next);
265               }
266               listing.push(next);
267             }
268           }
269
270           return listing;
271         }
272
273         return recursiveListingInternal('', [], dir);
274     }
275
276 };