Bug 799226 - Optimize |OS.File.exists| r=Yoric
authorAndres Hernandez <andres@appcoast.com>
Tue, 16 Oct 2012 09:39:27 -0600
changeset 110601 a25b864146d19835001ecd6bdee7e1a820a3f776
parent 110600 69e943a96a429913bc4a11322cb21456cdef83e2
child 110602 5013505b39301834fb3180b71d742bea30234152
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersYoric
bugs799226
milestone19.0a1
Bug 799226 - Optimize |OS.File.exists| r=Yoric
toolkit/components/osfile/osfile_async_front.jsm
toolkit/components/osfile/osfile_async_worker.js
toolkit/components/osfile/osfile_shared_front.jsm
toolkit/components/osfile/osfile_unix_front.jsm
toolkit/components/osfile/osfile_win_front.jsm
toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js
--- a/toolkit/components/osfile/osfile_async_front.jsm
+++ b/toolkit/components/osfile/osfile_async_front.jsm
@@ -614,16 +614,28 @@ File.makeDir = function makeDir(path, op
  * read from the file.
  */
 File.read = function read(path, bytes) {
   return Scheduler.post("read",
     [Type.path.toMsg(path), bytes], path);
 };
 
 /**
+ * Find outs if a file exists.
+ *
+ * @param {string} path The path to the file.
+ *
+ * @return {bool} true if the file exists, false otherwise.
+ */
+File.exists = function exists(path) {
+  return Scheduler.post("exists",
+    [Type.path.toMsg(path)], path);
+};
+
+/**
  * Write a file, atomically.
  *
  * By opposition to a regular |write|, this operation ensures that,
  * until the contents are fully written, the destination file is
  * not modified.
  *
  * Important note: In the current implementation, option |tmpPath|
  * is required. This requirement should disappear as part of bug 793660.
--- a/toolkit/components/osfile/osfile_async_worker.js
+++ b/toolkit/components/osfile/osfile_async_worker.js
@@ -205,16 +205,19 @@ if (this.Components) {
        },
        open: function open(path, mode, options) {
          let file = File.open(Type.path.fromMsg(path), mode, options);
          return OpenedFiles.add(file);
        },
        read: function read(path, bytes) {
          return File.read(Type.path.fromMsg(path), bytes);
        },
+       exists: function exists(path) {
+         return File.exists(Type.path.fromMsg(path));
+       },
        writeAtomic: function writeAtomic(path, buffer, options) {
          if (options.tmpPath) {
            options.tmpPath = Type.path.fromMsg(options.tmpPath);
          }
          return File.writeAtomic(Type.path.fromMsg(path),
                                  Type.voidptr_t.fromMsg(buffer),
                                  options
                                 );
--- a/toolkit/components/osfile/osfile_shared_front.jsm
+++ b/toolkit/components/osfile/osfile_shared_front.jsm
@@ -303,33 +303,16 @@ AbstractFile.read = function read(path, 
   try {
     return file.read(bytes);
   } finally {
     file.close();
   }
 };
 
 /**
- * Find outs if a file exists.
- *
- * @param {string} path The path to the file.
- *
- * @return {bool} true if the file exists, false otherwise.
- */
-AbstractFile.exists = function exists(path) {
-  try {
-    let file = exports.OS.File.open(path);
-    file.close();
-    return true;
-  } catch (x) {
-    return false;
-  }
-};
-
-/**
  * Write a file, atomically.
  *
  * By opposition to a regular |write|, this operation ensures that,
  * until the contents are fully written, the destination file is
  * not modified.
  *
  * Important note: In the current implementation, option |tmpPath|
  * is required. This requirement should disappear as part of bug 793660.
--- a/toolkit/components/osfile/osfile_unix_front.jsm
+++ b/toolkit/components/osfile/osfile_unix_front.jsm
@@ -253,16 +253,31 @@
              flags |= Const.O_APPEND | Const.O_CREAT;
            }
          }
        }
        return error_or_file(UnixFile.open(path, flags, omode));
      };
 
      /**
+      * Checks if a file exists
+      *
+      * @param {string} path The path to the file.
+      *
+      * @return {bool} true if the file exists, false otherwise.
+      */
+     File.exists = function Unix_exists(path) {
+       if (UnixFile.access(path, OS.Constants.libc.F_OK) == -1) {
+         return false;
+       } else {
+         return true;
+       }
+     };
+
+     /**
       * Remove an existing file.
       *
       * @param {string} path The name of the file.
       */
      File.remove = function remove(path) {
        throw_on_negative("remove",
          UnixFile.unlink(path)
        );
@@ -823,17 +838,16 @@
          throw_on_negative("stat", UnixFile.lstat(path, gStatDataPtr));
        } else {
          throw_on_negative("stat", UnixFile.stat(path, gStatDataPtr));
        }
        return new File.Info(gStatData);
      };
 
      File.read = exports.OS.Shared.AbstractFile.read;
-     File.exists = exports.OS.Shared.AbstractFile.exists;
      File.writeAtomic = exports.OS.Shared.AbstractFile.writeAtomic;
 
      /**
       * Get/set the current directory.
       */
      Object.defineProperty(File, "curDir", {
          set: function(path) {
            throw_on_negative("curDir",
--- a/toolkit/components/osfile/osfile_win_front.jsm
+++ b/toolkit/components/osfile/osfile_win_front.jsm
@@ -313,16 +313,33 @@
        // Now, perform manual truncation
        file.setPosition(0, File.POS_START);
        throw_on_zero("open",
          WinFile.SetEndOfFile(file.fd));
        return file;
      };
 
      /**
+      * Checks if a file exists
+      *
+      * @param {string} path The path to the file.
+      *
+      * @return {bool} true if the file exists, false otherwise.
+      */
+     File.exists = function Win_exists(path) {
+       try {
+         let file = File.open(path);
+         file.close();
+         return true;
+       } catch (x) {
+         return false;
+       }
+     };
+
+     /**
       * Remove an existing file.
       *
       * @param {string} path The name of the file.
       * @throws {OS.File.Error} In case of I/O error.
       */
      File.remove = function remove(path) {
        throw_on_zero("remove",
          WinFile.DeleteFile(path));
@@ -817,17 +834,16 @@
        // Directories can be opened neither for reading(!) nor for writing
        winAccess: 0,
        // Directories can only be opened with backup semantics(!)
        winFlags: OS.Constants.Win.FILE_FLAG_BACKUP_SEMANTICS,
        winDisposition: OS.Constants.Win.OPEN_EXISTING
      };
 
      File.read = exports.OS.Shared.AbstractFile.read;
-     File.exists = exports.OS.Shared.AbstractFile.exists;
      File.writeAtomic = exports.OS.Shared.AbstractFile.writeAtomic;
 
      /**
       * Get/set the current directory.
       */
      Object.defineProperty(File, "curDir", {
          set: function(path) {
            throw_on_zero("set curDir",
--- a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
+++ b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
@@ -167,17 +167,17 @@ let reference_compare_files = function r
 };
 
 let test = maketest("Main",
   function main(test) {
     SimpleTest.waitForExplicitFinish();
     let tests = [test_constants, test_path, test_open, test_stat,
                  test_read_write, test_read_write_all,
                  test_position, test_copy,
-                 test_iter];
+                 test_iter, test_exists];
     let current = 0;
     let aux = function aux() {
       if (current >= tests.length) {
         info("Test is over");
         SimpleTest.finish();
         return null;
       }
       let test = tests[current++];
@@ -958,9 +958,30 @@ let test_iter = maketest("iter",
       function cleanup() {
         if (iterator) {
           iterator.close();
         }
       }
     );
 
     return promise;
-});
\ No newline at end of file
+});
+
+/**
+ * Test OS.File.prototype.{exists}
+ */
+let test_exists = maketest("exists",
+  function exists(test) {
+    let promise;
+
+    promise = OS.File.exists(EXISTING_FILE);
+    promise = promise.then(function exists_worked(aExists) {
+      test.ok(aExists, "file exists");
+      return OS.File.exists(EXISTING_FILE + ".tmp");
+    });
+
+    promise = promise.then(function exists_on_absent_file_worked(aExists) {
+      test.ok(!aExists, "file does not exists");
+    });
+
+    // Do not forget to return the promise.
+    return promise;
+});
--- a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js
+++ b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js
@@ -32,16 +32,17 @@ self.onmessage = function onmessage_star
     test_copy_existing_file();
     test_readall_writeall_file();
     test_position();
     test_move_file();
     test_iter_dir();
     test_mkdir();
     test_info();
     test_path();
+    test_exists_file();
   } catch (x) {
     log("Catching error: " + x);
     log("Stack: " + x.stack);
     log("Source: " + x.toSource());
     ok(false, x.toString() + "\n" + x.stack);
   }
   finish();
 };
@@ -767,8 +768,21 @@ function test_path()
   let abdotsc = OS.Path.join("a", "b", "..", "c");
   is(OS.Path.normalize(abdotsc), OS.Path.join("a", "c"), "normalize a/b/../c");
 
   let adotsdotsdots = OS.Path.join("a", "..", "..", "..");
   is(OS.Path.normalize(adotsdotsdots), OS.Path.join("..", ".."), "normalize a/../../..");
 
   ok(true, "test_path: Complete");
 }
+
+/**
+ * Test the file |exists| method.
+ */
+function test_exists_file()
+{
+  let file_name = OS.Path.join("chrome", "toolkit", "components" ,"osfile",
+                               "tests", "mochi", "test_osfile_front.xul");
+  ok(true, "test_exists_file: starting");
+  ok(OS.File.exists(file_name), "test_exists_file: file exists (OS.File.exists)");
+  ok(!OS.File.exists(file_name + ".tmp"), "test_exists_file: file does not exists (OS.File.exists)");
+  ok(true, "test_exists_file: complete");
+}