Bug 804566 - [OS.File] Add an option ignoreExisting to OS.File.makeDir r=dteller
authorEduard Neculaesi <eduardnem@gmail.com>
Wed, 31 Oct 2012 01:19:44 +0200
changeset 112010 a33857ce6108
parent 112009 7301a942c554
child 112011 e2cb5f94ead6
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersdteller
bugs804566
milestone19.0a1
Bug 804566 - [OS.File] Add an option ignoreExisting to OS.File.makeDir r=dteller
toolkit/components/osfile/osfile_async_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
@@ -592,16 +592,18 @@ File.remove = function remove(path) {
  * @param {string} path The name of the directory.
  * @param {*=} options Additional options.
  * Implementations may interpret the following fields:
  *
  * - {C pointer} winSecurity If specified, security attributes
  * as per winapi function |CreateDirectory|. If unspecified,
  * use the default security descriptor, inherited from the
  * parent directory.
+ * - {bool} ignoreExisting If |true|, do not fail if the
+ * directory already exists.
  */
 File.makeDir = function makeDir(path, options) {
   return Scheduler.post("makeDir",
     [Type.path.toMsg(path), options], path);
 };
 
 /**
  * Return the contents of a file
--- a/toolkit/components/osfile/osfile_unix_front.jsm
+++ b/toolkit/components/osfile/osfile_unix_front.jsm
@@ -313,22 +313,28 @@
       * @param {string} path The name of the directory.
       * @param {*=} options Additional options. This
       * implementation interprets the following fields:
       *
       * - {number} unixMode If specified, a file creation mode,
       * as per libc function |mkdir|. If unspecified, dirs are
       * created with a default mode of 0700 (dir is private to
       * the user, the user can read, write and execute).
+      * - {bool} ignoreExisting If |true|, do not fail if the
+      * directory already exists.
       */
      File.makeDir = function makeDir(path, options) {
        options = options || noOptions;
        let omode = options.unixMode || DEFAULT_UNIX_MODE_DIR;
-       throw_on_negative("makeDir",
-         UnixFile.mkdir(path, omode));
+       let result = UnixFile.mkdir(path, omode);
+       if (result != -1 ||
+           options.ignoreExisting && ctypes.errno == OS.Constants.libc.EEXIST) {
+        return;
+       }
+       throw new File.Error("makeDir");
      };
 
      /**
       * Copy a file to a destination.
       *
       * @param {string} sourcePath The platform-specific path at which
       * the file may currently be found.
       * @param {string} destPath The platform-specific path at which the
--- a/toolkit/components/osfile/osfile_win_front.jsm
+++ b/toolkit/components/osfile/osfile_win_front.jsm
@@ -371,22 +371,29 @@
       * @param {string} path The name of the directory.
       * @param {*=} options Additional options. This
       * implementation interprets the following fields:
       *
       * - {C pointer} winSecurity If specified, security attributes
       * as per winapi function |CreateDirectory|. If unspecified,
       * use the default security descriptor, inherited from the
       * parent directory.
+      * - {bool} ignoreExisting If |true|, do not fail if the
+      * directory already exists.
       */
      File.makeDir = function makeDir(path, options) {
        options = options || noOptions;
        let security = options.winSecurity || null;
-       throw_on_zero("makeDir",
-         WinFile.CreateDirectory(path, security));
+       let result = WinFile.CreateDirectory(path, security);
+       if (result ||
+           options.ignoreExisting &&
+           ctypes.winLastError == OS.Constants.Win.ERROR_ALREADY_EXISTS) {
+        return;
+       }
+       throw new File.Error("makeDir");
      };
 
      /**
       * Copy a file to a destination.
       *
       * @param {string} sourcePath The platform-specific path at which
       * the file may currently be found.
       * @param {string} destPath The platform-specific path at which the
--- a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
+++ b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
@@ -473,16 +473,24 @@ let test_mkdir = maketest("mkdir", funct
     }
 
     // Creating a directory (should succeed)
     test.ok(true, "Creating a directory");
     yield OS.File.makeDir(DIRNAME);
     let stat = yield OS.File.stat(DIRNAME);
     test.ok(stat.isDir, "I have effectively created a directory");
 
+    // Creating a directory with ignoreExisting (should succeed)
+    try {
+      yield OS.File.makeDir(DIRNAME, {ignoreExisting: true});
+      test.ok(true, "Creating a directory with ignoreExisting succeeds");
+    } catch(err) {
+      test.ok(false, "Creating a directory with ignoreExisting fails");
+    }
+
     // Creating a directory (should fail)
     try {
       yield OS.File.makeDir(DIRNAME);
       test.fail("Creating over an existing directory should have failed");
     } catch (err) {
       test.ok(err, "Creating over an existing directory throws the right error");
       test.ok(err instanceof OS.File.Error, "Error is an OS.File.Error");
       test.ok(err.becauseExists, "Error mentions that the file already exists");
--- a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js
+++ b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js
@@ -740,16 +740,25 @@ function test_mkdir()
   exn = null;
   try {
     OS.File.makeDir(dirName);
   } catch (x) {
     exn = x;
   }
   ok(exn && exn instanceof OS.File.Error && exn.becauseExists, "test_mkdir: makeDir over an existing directory failed for all the right reasons");
 
+  ok(true, "test_mkdir: Creating directory that already exists with ignoreExisting");
+  exn = null;
+  try {
+    OS.File.makeDir(dirName, {ignoreExisting: true});
+  } catch(x) {
+    exn = x;
+  }
+  ok(!exn, "test_mkdir: makeDir over an existing directory with ignoreExisting is successful");
+
   // Cleanup - and check that we have cleaned up
   OS.File.removeEmptyDir(dirName);
 
   try {
     OS.File.stat(dirName);
     ok(false, "test_mkdir: Directory was not removed");
   } catch (x) {
     ok(x instanceof OS.File.Error && x.becauseNoSuchFile, "test_mkdir: Directory was removed");