File API tweaks
authorTim Caswell <tim@creationix.com>
Wed, 17 Feb 2010 07:06:26 +0000 (01:06 -0600)
committerRyan Dahl <ry@tinyclouds.org>
Wed, 17 Feb 2010 07:55:53 +0000 (23:55 -0800)
- Rename fs.cat to fs.readFile
- Move file.write to fs.writeFile
- Allow strings for the flag argument to fs.open
  ("r", "r+", "w", "w+", "a", "a+")
- Remove the unused 'File' module / class

doc/api.txt
lib/file.js
src/node.js
test/mjsunit/disabled/test-fs-sendfile.js
test/mjsunit/test-buffered-file.js [deleted file]
test/mjsunit/test-eio-race.js
test/mjsunit/test-eio-race2.js
test/mjsunit/test-file-read-noexist.js [moved from test/mjsunit/test-file-cat-noexist.js with 91% similarity]
test/mjsunit/test-fs-write.js
test/mjsunit/test-stat-handler.js
test/mjsunit/test-sync-fileread.js [moved from test/mjsunit/test-sync-cat.js with 65% similarity]

index bc1fe9f..9ddca51 100644 (file)
@@ -709,8 +709,10 @@ See the +fs.Stats+ section below for more information.
   - on error: no parameters.
 
 
-+fs.open(path, flags, mode)+::
++fs.open(path, flags, mode=0666)+::
   See open(2). The constants like +O_CREAT+ are defined at +process.O_CREAT+.
+  Also you can use the strings "r", "r+", "w", "w+", "a", or "a+" as aliases
+  to the common flag combinations.
   - on success: +fd+ is given as the parameter.
   - on error: no parameters.
 
@@ -735,11 +737,11 @@ See the +fs.Stats+ section below for more information.
   - on success: returns +data, bytes_read+, what was read from the file.
   - on error: no parameters.
 
-+fs.cat(filename, encoding="utf8")+::
++fs.readFile(filename, encoding="utf8")+::
 Outputs the entire contents of a file. Example:
 +
 --------------------------------
-fs.cat("/etc/passwd").addCallback(function (content) {
+fs.readFile("/etc/passwd").addCallback(function (content) {
   sys.puts(content);
 });
 --------------------------------
@@ -747,6 +749,18 @@ fs.cat("/etc/passwd").addCallback(function (content) {
 - on success: returns +data+, what was read from the file.
 - on error: no parameters.
 
++fs.writeFile(filename, data, encoding="utf8")+::
+Writes data to a file. Example:
++
+--------------------------------
+fs.writeFile("message.txt", "Hello Node").addCallback(function () {
+  sys.puts("It's saved!");
+});
+--------------------------------
++
+- on success: no parameters.
+- on error: no parameters.
+
 ==== +fs.Stats+
 
 Objects returned from +fs.stat()+ are of this type.
index c024f54..d8c1a6c 100644 (file)
@@ -1,156 +1 @@
-var fs = require("./fs");
-var events = require('events');
-/*jslint onevar: true, undef: true, eqeqeq: true, plusplus: true, regexp: true, newcap: true, immed: true */
-/*globals exports, node, __filename */
-
-exports.debugLevel = 0; // Increase to get more verbose debug output
-
-function debugMessage (msg) {
-  if (exports.debugLevel > 0) {
-    process.error(__filename + ": " + msg.toString());
-  }
-}
-
-function debugObject (obj) {
-  if (exports.debugLevel > 0) {
-    process.error(__filename + ": " + JSON.stringify(obj));
-  }
-}
-
-exports.read = fs.cat;
-
-exports.write = function (filename, data, encoding) {
-  var promise = new events.Promise();
-
-  encoding = encoding || "utf8"; // default to utf8
-
-  fs.open(filename, process.O_WRONLY | process.O_TRUNC | process.O_CREAT, 0666)
-    .addCallback(function (fd) {
-      function doWrite (_data) {
-        fs.write(fd, _data, 0, encoding)
-          .addErrback(function () {
-            fs.close(fd);
-            promise.emitError();
-          })
-          .addCallback(function (written) {
-            if (written === _data.length) {
-              fs.close(fd);
-              promise.emitSuccess();
-            } else {
-              doWrite(_data.slice(written));
-            }
-          });
-      }
-      doWrite(data);
-    })
-    .addErrback(function () {
-      promise.emitError();
-    });
-
-  return promise;
-};
-
-exports.File = function (filename, mode, options) {
-  var self = this;
-
-  options = options || {};
-  self.encoding = options.encoding || "utf8";
-
-  self.filename = filename;
-
-  self.actionQueue = [];
-  self.currentAction = null;
-
-  switch (mode) {
-    case "r":
-      self.flags = process.O_RDONLY;
-      break;
-
-    case "r+":
-      self.flags = process.O_RDWR;
-      break;
-
-    case "w":
-      self.flags = process.O_CREAT | process.O_TRUNC | process.O_WRONLY;
-      break;
-
-    case "w+":
-      self.flags = process.O_CREAT | process.O_TRUNC | process.O_RDWR;
-      break;
-
-    case "a":
-      self.flags = process.O_APPEND | process.O_CREAT | process.O_WRONLY; 
-      break;
-
-    case "a+":
-      self.flags = process.O_APPEND | process.O_CREAT | process.O_RDWR; 
-      break;
-
-    default:
-      throw new Error("Unknown mode");
-  }
-
-  self.open(self.filename, self.flags, 0666).addCallback(function (fd) {
-    debugMessage(self.filename + " opened. fd = " + fd);
-    self.fd = fd;
-  }).addErrback(function () {
-    self.emit("error", ["open"]);
-  });
-};
-
-var proto = exports.File.prototype;
-
-proto._maybeDispatch = function () {
-  var self, args, method, promise, userPromise;
-  
-  self = this;
-
-  if (self.currentAction) { return; }
-  self.currentAction = self.actionQueue.shift();
-  if (!self.currentAction) { return; }
-
-  debugObject(self.currentAction);
-
-  args = self.currentAction.args || [];
-  method = self.currentAction.method;
-
-
-  if (method !== "open") {
-    args.unshift(self.fd);
-  }
-
-  if (!args[3] && (method === "read" || method === "write")) {
-    args[3] = self.encoding;
-  }
-  promise = fs[method].apply(self, args);
-
-  userPromise = self.currentAction.promise;
-
-  promise.addCallback(function () {
-    process.assert(self.currentAction.promise === userPromise);
-    userPromise.emitSuccess.apply(userPromise, arguments);
-    self.currentAction = null;
-    self._maybeDispatch();
-  }).addErrback(function () {
-    debugMessage("Error in method " + method);
-    process.assert(self.currentAction.promise === userPromise);
-    userPromise.emitError.apply(userPromise, arguments);
-    self.currentAction = null;
-    self._maybeDispatch();
-  });
-};
-
-proto._queueAction = function (method, args) {
-  var userPromise = new events.Promise();
-  this.actionQueue.push({ method: method, args: args, promise: userPromise });
-  this._maybeDispatch();
-  return userPromise;
-};
-
-
-(["open", "write", "read", "close"]).forEach(function (name) {
-  proto[name] = function () {
-    return this._queueAction(name, Array.prototype.slice.call(arguments, 0));
-  };
-});
-
+throw new Error("The 'file' module has been removed. 'file.read' is now 'fs.readFile', and 'file.write' is now 'fs.writeFile'.");
index 905757c..302790f 100644 (file)
@@ -526,6 +526,23 @@ var fsModule = createInternalModule("fs", function (exports) {
       }
     };
   }
+  
+  // Used by fs.open and friends
+  function stringToFlags(flag) {
+    // Only mess with strings
+    if (typeof flag !== 'string') {
+      return flag;
+    }
+    switch (flag) {
+      case "r": return process.O_RDONLY;
+      case "r+": return process.O_RDWR;
+      case "w": return process.O_CREAT | process.O_TRUNC | process.O_WRONLY;
+      case "w+": return process.O_CREAT | process.O_TRUNC | process.O_RDWR;
+      case "a": return process.O_APPEND | process.O_CREAT | process.O_WRONLY; 
+      case "a+": return process.O_APPEND | process.O_CREAT | process.O_RDWR;
+      default: throw new Error("Unknown file open flag: " + flag);
+    }
+  }
 
   // Yes, the follow could be easily DRYed up but I provide the explicit
   // list to make the arguments clear.
@@ -541,13 +558,15 @@ var fsModule = createInternalModule("fs", function (exports) {
   };
 
   exports.open = function (path, flags, mode) {
+    if (mode === undefined) { mode = 0666; }
     var promise = new events.Promise();
-    process.fs.open(path, flags, mode, callback(promise));
+    process.fs.open(path, stringToFlags(flags), mode, callback(promise));
     return promise;
   };
 
   exports.openSync = function (path, flags, mode) {
-    return process.fs.open(path, flags, mode);
+    if (mode === undefined) { mode = 0666; }
+    return process.fs.open(path, stringToFlags(flags), mode);
   };
 
   exports.read = function (fd, length, position, encoding) {
@@ -654,13 +673,54 @@ var fsModule = createInternalModule("fs", function (exports) {
     return process.fs.unlink(path);
   };
 
+  exports.writeFile = function (path, data, encoding) {
+    var promise = new events.Promise();
+    encoding = encoding || "utf8"; // default to utf8
+
+    fs.open(path, "w")
+      .addCallback(function (fd) {
+        function doWrite (_data) {
+          fs.write(fd, _data, 0, encoding)
+            .addErrback(function () {
+              fs.close(fd);
+              promise.emitError();
+            })
+            .addCallback(function (written) {
+              if (written === _data.length) {
+                fs.close(fd);
+                promise.emitSuccess();
+              } else {
+                doWrite(_data.slice(written));
+              }
+            });
+        }
+        doWrite(data);
+      })
+      .addErrback(function () {
+        promise.emitError();
+      });
+
+    return promise;
+    
+  };
+  
+  exports.writeFileSync = function (path, data, encoding) {
+    encoding = encoding || "utf8"; // default to utf8
+    var fd = exports.openSync(path, "w");
+    return process.fs.write(fd, data, 0, encoding);
+  };
+  
+  
+  exports.cat = function () {
+    throw new Error("fs.cat is deprecated. Please use fs.readFile instead.");
+  };
 
-  exports.cat = function (path, encoding) {
+  exports.readFile = function (path, encoding) {
     var promise = new events.Promise();
 
     encoding = encoding || "utf8"; // default to utf8
 
-    exports.open(path, process.O_RDONLY, 0666).addCallback(function (fd) {
+    exports.open(path, "r").addCallback(function (fd) {
       var content = "", pos = 0;
 
       function readChunk () {
@@ -689,11 +749,15 @@ var fsModule = createInternalModule("fs", function (exports) {
     return promise;
   };
 
-  exports.catSync = function (path, encoding) {
+  exports.catSync = function () {
+    throw new Error("fs.catSync is deprecated. Please use fs.readFileSync instead.");
+  };
+
+  exports.readFileSync = function (path, encoding) {
     encoding = encoding || "utf8"; // default to utf8
 
     var
-      fd = exports.openSync(path, process.O_RDONLY, 0666),
+      fd = exports.openSync(path, "r"),
       content = '',
       pos = 0,
       r;
@@ -939,7 +1003,7 @@ function cat (id, loadPromise) {
         loadPromise.emitError(new Error("could not load core module \"http\""));
       });
   } else {
-    promise = fs.cat(id);
+    promise = fs.readFile(id);
   }
 
   return promise;
index 93cac12..41e16df 100644 (file)
@@ -19,8 +19,8 @@ server.listen(PORT);
 
 var client = tcp.createConnection(PORT);
 client.addListener("connect", function () {
-  posix.open(x,process.O_RDONLY, 0666).addCallback(function (fd) {
-    posix.sendfile(client.fd, fd, 0, expected.length).addCallback(function (size) {
+  fs.open(x, 'r').addCallback(function (fd) {
+    fs.sendfile(client.fd, fd, 0, expected.length).addCallback(function (size) {
       assert.equal(expected.length, size);
     });
   });
diff --git a/test/mjsunit/test-buffered-file.js b/test/mjsunit/test-buffered-file.js
deleted file mode 100644 (file)
index dbea229..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-process.mixin(require("./common"));
-
-var testTxt = path.join(fixturesDir, "test.txt");
-
-var libDir = path.join(testDir, "../../lib");
-require.paths.unshift(libDir);
-process.mixin(require("file"));
-
-var fileUnlinked = false;
-
-var file = new File(testTxt, "w+");
-file.write("hello\n");
-file.write("world\n");
-setTimeout(function () {
-  file.write("hello\n");
-  file.write("world\n");
-  file.close().addCallback(function () {
-    error("file closed...");
-    var out = fs.cat(testTxt).wait();
-    print("the file contains: ");
-    p(out);
-    assert.equal("hello\nworld\nhello\nworld\n", out);
-    var file2 = new File(testTxt, "r");
-    file2.read(5).addCallback(function (data) {
-      puts("read(5): " + JSON.stringify(data));
-      assert.equal("hello", data);
-      fs.unlink(testTxt).addCallback(function () {
-        fileUnlinked = true;
-      });
-    });
-    file2.close();
-  });
-}, 10);
-
-process.addListener("exit", function () {
-  assert.equal(true, fileUnlinked);
-  puts("done");
-});
index 20eb382..cae4bc7 100644 (file)
@@ -36,7 +36,7 @@ function tryToKillEventLoop() {
 
 // Generate a lot of thread pool events
 var pos = 0;
-fs.open('/dev/zero', process.O_RDONLY, 0666).addCallback(function (rd) {
+fs.open('/dev/zero', "r").addCallback(function (rd) {
   function readChunk () {
     fs.read(rd, 1024, pos, 'binary').addCallback(function (chunk, bytesRead) {
       if (chunk) {
index 5e904f2..d11f5be 100644 (file)
@@ -8,7 +8,7 @@ setTimeout(function () {
   N = 30;
   for (var i=0; i < N; i++) {
     puts("start " + i);
-    fs.cat(testTxt).addCallback(function(data) {
+    fs.readFile(testTxt).addCallback(function(data) {
       puts("finish");
     }).addErrback(function (e) {
       puts("error! " + e);
similarity index 91%
rename from test/mjsunit/test-file-cat-noexist.js
rename to test/mjsunit/test-file-read-noexist.js
index d11e002..9e2b2ae 100644 (file)
@@ -2,7 +2,7 @@ process.mixin(require("./common"));
 var got_error = false;
 
 var filename = path.join(fixturesDir, "does_not_exist.txt");
-var promise = fs.cat(filename, "raw");
+var promise = fs.readFile(filename, "raw");
 
 promise.addCallback(function (content) {
   debug("cat returned some content: " + content);
index f8074d5..198c932 100644 (file)
@@ -4,10 +4,10 @@ var fn = path.join(fixturesDir, "write.txt");
 var expected = "hello";
 var found;
 
-fs.open(fn, process.O_WRONLY | process.O_TRUNC | process.O_CREAT, 0644).addCallback(function (file) {
+fs.open(fn, 'w', 0644).addCallback(function (file) {
   fs.write(file, expected, 0, "utf8").addCallback(function() {
     fs.close(file).addCallback(function() {
-      fs.cat(fn, process.UTF8).addCallback(function(contents) {
+      fs.readFile(fn, process.UTF8).addCallback(function(contents) {
         found = contents;
         fs.unlink(fn).wait();
       });
index 4604c42..ee3cd8b 100644 (file)
@@ -16,12 +16,11 @@ process.watchFile(f, function (curr, prev) {
 });
 
 
-var File = require("file").File;
-
-var file = new File(f, 'w+');
-file.write('xyz\n');
-file.close().wait();
+var fs = require("fs");
 
+var fd = fs.openSync(f, "w+");
+fs.writeSync(fd, 'xyz\n');
+fs.closeSync(fd);
 
 process.addListener("exit", function () {
   assert.equal(true, changes > 0);
similarity index 65%
rename from test/mjsunit/test-sync-cat.js
rename to test/mjsunit/test-sync-fileread.js
index a602b1a..bc80eec 100644 (file)
@@ -2,4 +2,4 @@ process.mixin(require('./common'));
 
 var fixture = path.join(__dirname, "fixtures/x.txt");
 
-assert.equal("xyz\n", fs.catSync(fixture));
\ No newline at end of file
+assert.equal("xyz\n", fs.readFileSync(fixture));
\ No newline at end of file