Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add Filesystem utilities.

  • Loading branch information...
commit cc885211666287effcb715b5d0c95775bded9150 1 parent e001e2e
@npcode authored
Showing with 428 additions and 0 deletions.
  1. +4 −0 Makefile
  2. +62 −0 README.md
  3. +131 −0 fsutil.js
  4. +231 −0 test/fsutil.test.js
View
4 Makefile
@@ -0,0 +1,4 @@
+test:
+ mocha --reporter list -u tdd
+
+.PHONY: test
View
62 README.md
@@ -0,0 +1,62 @@
+Filesystem Utilities
+====================
+
+Filesystem utilities for Node.js.
+
+These are all synchronous functions except cp and cp_r.
+
+Requirements
+------------
+
+* [mocha](http://visionmedia.github.com/mocha/) (if you want to run tests)
+
+API
+---
+
+#### rm_rf(path)
+
+Remove the directory on `path` recursively.
+
+#### mkdir_p(path)
+
+Create a directory and all its parent directories.
+
+#### cp(src, dest, callback)
+
+Copy a file content `src` to `dest`.
+
+#### cp_r(src, dest, callback)
+
+Copy file contents `src` to `dest` recursively.
+
+#### ln_s(src, path)
+
+Creates a symbolic link `path` which points to `src`.
+
+#### ln_sf(src, path)
+
+Creates a symbolic link `path` which points to `src`. If `path` already exists, overwrite it.
+
+### cd(path)
+
+Change the current working directory.
+
+### pwd()
+
+Get the current working directory.
+
+#### chmod(mode, path)
+
+Change permission bits on `path`.
+
+#### chown(uid, gid, path)
+
+Change the owner of the file or directory on `path`
+
+#### chown_R(uid, gid, path)
+
+Change the owner of the file or directory on `path` recursively.
+
+#### fwrite_p(path, data)
+
+Write a file on `path` after create all its parent directories if necessary.
View
131 fsutil.js
@@ -0,0 +1,131 @@
+var fs = require('fs');
+var pth = require('path');
+var util = require('util');
+
+pth.sep = pth.sep || (process.platform == 'win32' ? '\\' : '/');
+
+var rm_rf = function(path) {
+ try {
+ var stat = fs.lstatSync(path);
+ } catch(e) {
+ return false;
+ }
+
+ if (stat.isDirectory()) {
+ fs.readdirSync(path).forEach(function (filename) {
+ rm_rf(pth.join(path, filename));
+ });
+ fs.rmdirSync(path);
+ } else {
+ fs.unlinkSync(path);
+ }
+}
+
+var _mkdir_p = function(path_segments) {
+ var base = '';
+ var paths_to_create = [];
+ if (!path_segments.every(function (segment) {
+ base = pth.join(base, segment);
+ if (!pth.existsSync(base)) {
+ paths_to_create.push(base);
+ return true;
+ }
+ return fs.statSync(base).isDirectory();
+ })) {
+ return false;
+ }
+
+ paths_to_create.forEach(function (segment) {
+ fs.mkdirSync(segment);
+ });
+
+}
+
+var mkdir_p = function(path) {
+ return _mkdir_p(pth.normalize(path).split(pth.sep));
+}
+
+var fwrite_p = function(path, data) {
+ var path_segments = pth.normalize(path).split(pth.sep);
+ _mkdir_p(path_segments.slice(0, path_segments.length - 1));
+ return fs.writeFileSync(path, data);
+}
+
+var cp = function(src, dst, callback) {
+ var is = fs.createReadStream(src);
+ var os = fs.createWriteStream(dst);
+ util.pump(is, os, callback);
+}
+
+var cp_r = function(src, dst, callback) {
+ var self = this;
+
+ if (fs.statSync(src).isDirectory()) {
+ fs.mkdirSync(dst);
+ var files = fs.readdirSync(src);
+ var num_of_files = files.length;
+ if (num_of_files == 0) {
+ callback(null);
+ }
+ var cnt = 0;
+ var cb = function(err) {
+ if (err) throw err;
+ if (++cnt >= num_of_files) {
+ callback(err);
+ }
+ }
+ files.forEach(function (filename) {
+ self.cp_r(pth.join(src, filename), pth.join(dst, filename), cb);
+ });
+ } else {
+ cp(src, dst, callback);
+ }
+}
+
+var ln_sf = function(src, path) {
+ if (pth.existsSync(path)) {
+ if (fs.statSync(path).isDirectory()) {
+ var segments = src.split(pth.sep);
+ filename = segments.split(pth.sep)[segments.length - 1]
+ fs.symlinkSync(src, pth.join(path, filename));
+ } else {
+ fs.unlinkSync(path);
+ fs.symlinkSync(src, path);
+ }
+ } else {
+ fs.symlinkSync(src, path);
+ }
+}
+
+var chown_R = function(uid, gid, path) {
+ var self = this;
+
+ if (fs.statSync(path).isDirectory()) {
+ var files = fs.readdirSync(path);
+ files.forEach(function (filename) {
+ self.chown_R(uid, gid, pth.join(path, filename));
+ });
+ fs.chownSync(path, uid, gid);
+ } else {
+ fs.chownSync(path, uid, gid);
+ }
+}
+
+exports.rm_rf = rm_rf;
+exports.mkdir_p = mkdir_p;
+exports.fwrite_p = fwrite_p;
+exports.cp = cp;
+exports.cp_r = cp_r;
+exports.ln_s = fs.symlinkSync;
+exports.ln_sf = ln_sf;
+exports.cd = process.chdir;
+exports.pwd = process.cwd;
+exports.mv = fs.renameSync;
+exports.rm = fs.unlinkSync;
+exports.chmod = function(mode, path) { return fs.chmodSync(path, mode); };
+exports.chown = function(uid, gid, path) { return fs.chownSync(path, uid, gid); };
+exports.chown_R = chown_R;
+// install(src, dest, mode = <src's>, options)
+// chown(uid, gid, list, options)
+// chown_R(uid, gid, list, options)
+// touch(list, options)
View
231 test/fsutil.test.js
@@ -0,0 +1,231 @@
+var assert = require('assert');
+var fsutil = require('../fsutil');
+var fs = require('fs');
+var path = require('path');
+
+suite('fsutil.rm_rf', function() {
+ setup(function(done) {
+ if (path.existsSync('a')) {
+ fs.rmdirSync('a');
+ }
+ if (path.existsSync('a/b')) {
+ fs.unlinkSync('a/b');
+ }
+ if (path.existsSync('b')) {
+ fs.rmdirSync('b');
+ }
+ if (path.existsSync('c')) {
+ fs.unlinkSync('c');
+ }
+ if (path.existsSync('d')) {
+ fs.unlinkSync('d');
+ }
+ done();
+ });
+
+ test('Remove given directory recursively.', function() {
+ fs.mkdirSync('a');
+ fs.writeFileSync('a/b', 'hello');
+ fsutil.rm_rf('a');
+ assert.ok(!path.existsSync('a'));
+ assert.ok(!path.existsSync('a/b'));
+ });
+
+ test('Remove a dead symbolic link.', function() {
+ fs.writeFileSync('c', 'hello');
+ fs.symlinkSync('c', 'd');
+ fs.unlinkSync('c');
+ fsutil.rm_rf('d');
+ assert.throws(function() {fs.lstatSync('d');});
+ });
+
+ teardown(function(done) {
+ if (path.existsSync('a')) {
+ fs.rmdirSync('a');
+ }
+ if (path.existsSync('a/b')) {
+ fs.unlinkSync('a/b');
+ }
+ if (path.existsSync('b')) {
+ fs.rmdirSync('b');
+ }
+ if (path.existsSync('c')) {
+ fs.unlinkSync('c');
+ }
+ if (path.existsSync('d')) {
+ fs.unlinkSync('d');
+ }
+ done();
+ });
+});
+
+suite('fsutil.mkdir_p', function() {
+ setup(function(done) {
+ if (path.existsSync('a/b')) {
+ fs.rmdirSync('a/b');
+ fs.rmdirSync('a');
+ }
+ done();
+ });
+
+ test('Create a directory and all its parent directories.', function(done) {
+ fsutil.mkdir_p('a/b');
+ assert.ok(path.existsSync('a'));
+ assert.ok(path.existsSync('a/b'));
+ done();
+ });
+
+ teardown(function(done) {
+ if (path.existsSync('a/b')) {
+ fs.rmdirSync('a/b');
+ fs.rmdirSync('a');
+ }
+ done();
+ });
+});
+
+suite('fsutil.fwrite_p', function() {
+ setup(function(done) {
+ if (path.existsSync('a/b')) {
+ fs.unlinkSync('a/b');
+ fs.rmdirSync('a');
+ }
+ done();
+ });
+
+ test('Write a file after create all its parent directories.', function(done) {
+ fsutil.fwrite_p('a/b', 'hello');
+ assert.equal(fs.readFileSync('a/b'), 'hello');
+ done();
+ });
+
+ teardown(function(done) {
+ if (path.existsSync('a/b')) {
+ fs.unlinkSync('a/b');
+ fs.rmdirSync('a');
+ }
+ done();
+ });
+});
+
+suite('fsutil.cp', function() {
+ setup(function(done) {
+ fsutil.rm_rf('a');
+ fsutil.rm_rf('b');
+ done();
+ });
+
+ test('Copy a file content src to dest.', function(done) {
+ fs.writeFileSync('a', 'hello');
+ fsutil.cp('a', 'b', function() {
+ assert.equal(fs.readFileSync('b'), 'hello');
+ done();
+ });
+ });
+
+ teardown(function(done) {
+ fsutil.rm_rf('a');
+ fsutil.rm_rf('b');
+ done();
+ });
+});
+
+suite('fsutil.cp_r', function() {
+ setup(function(done) {
+ fsutil.rm_rf('a');
+ fsutil.rm_rf('b');
+ done();
+ });
+
+ test('Copy src to dest recursively.', function(done) {
+ fs.mkdirSync('a');
+ fs.mkdirSync('a/b');
+ fs.mkdirSync('a/c');
+ fs.writeFileSync('a/d', 'hello');
+
+ fsutil.cp_r('a', 'b', function() {
+ assert.equal(fs.readFileSync('b/d'), 'hello');
+ done();
+ });
+ });
+
+ teardown(function(done) {
+ fsutil.rm_rf('a');
+ fsutil.rm_rf('b');
+ done();
+ });
+});
+
+suite('fsutil.ln_sf', function() {
+ setup(function(done) {
+ fsutil.rm_rf('a');
+ fsutil.rm_rf('b');
+ done();
+ });
+
+ test('', function(done) {
+ fs.writeFileSync('a', 'hello');
+ fs.writeFileSync('b', 'bye');
+ fsutil.ln_sf('a', 'b');
+
+ assert.ok(fs.lstatSync('b').isSymbolicLink());
+ assert.equal(fs.readFileSync('b'), 'hello');
+ done();
+ });
+
+ teardown(function(done) {
+ fsutil.rm_rf('a');
+ fsutil.rm_rf('b');
+ done();
+ });
+});
+
+suite('fsutil.cd', function() {
+ setup(function(done) {
+ fsutil.rm_rf('a');
+ done();
+ });
+
+ test('Change the current working directory.', function(done) {
+ fs.mkdirSync('a');
+ var last_path = process.cwd();
+ fsutil.cd('a');
+ assert.equal(process.cwd(), path.join(last_path, 'a'));
+ done();
+ });
+
+ teardown(function(done) {
+ fsutil.rm_rf('a');
+ done();
+ });
+});
+
+suite('fsutil.pwd', function() {
+ test('Get the current working directory.', function() {
+ assert.equal(process.cwd(), fsutil.pwd());
+ });
+});
+
+// this test must be ran as root.
+suite('fsutil.chown_R', function() {
+ setup(function(done) {
+ fsutil.rm_rf('a');
+ done();
+ });
+
+ test('Change the owner of given path recursively.', function() {
+ fs.mkdirSync('a');
+ fs.writeFileSync('a/b', 'hello');
+ fsutil.chown_R(1000, 1000, 'a');
+ var stat = fs.statSync('a');
+ assert.equal(fs.statSync('a').uid, 1000);
+ assert.equal(fs.statSync('a').gid, 1000);
+ assert.equal(fs.statSync('a/b').uid, 1000);
+ assert.equal(fs.statSync('a/b').gid, 1000);
+ });
+
+ teardown(function(done) {
+ fsutil.rm_rf('a');
+ done();
+ });
+});
Please sign in to comment.
Something went wrong with that request. Please try again.