diff --git a/README.md b/README.md index 8eec7ad..674ca33 100644 --- a/README.md +++ b/README.md @@ -498,8 +498,8 @@ fs.link("/data/logs/august", "/data/logs/current", function(err) { #### fs.exists(path, callback) -Test whether or not the given path exists by checking with the file system. -Then call the callback argument with either true or false. +Test whether or not the given path exists by checking with the file system. +Then call the callback argument with either true or false. Example: @@ -596,7 +596,7 @@ Example: fs.mknod('/dir', 'DIRECTORY', function(err) { if(err) throw err; // /dir is now created - + // Create a file inside /dir fs.mknod('/dir/myfile', 'FILE', function(err) { if(err) throw err; @@ -897,7 +897,7 @@ fs.writeFile('/myfile', data, function (err) { fs.appendFile('/myfile', more, function (err) { if (err) throw err; - + // '/myfile' would now contain [1, 2, 3, 4, 5, 6, 7, 8] }); }); @@ -1088,20 +1088,31 @@ fs.writeFile('/data/subdir/file', 'data'); ### FileSystemShell Many common file system shell operations are available by using a `FileSystemShell` object. -The `FileSystemShell` is obtained from, and used in conjuction with a `FileSystem`, +The `FileSystemShell` is used in conjuction with a `FileSystem`, and provides augmented features. Many separate `FileSystemShell` objects can exist per `FileSystem`, but each `FileSystemShell` is bound to a single instance of a `FileSystem` for its lifetime. -A `FileSystemShell` is created using the `FileSystem.Shell()` function: +A `FileSystemShell` is created by calling `Filer.FileSystem().shell()`: ```javascript var fs = new Filer.FileSystem(); -var sh = fs.Shell(options); -var sh2 = fs.Shell(options); +var sh = fs.shell(options); +var sh2 = fs.shell(options); // sh and sh2 are two separate shells, each bound to fs ``` +Or, the original object can be accessed through `Filer`: + +```javascript +var fs = new Filer.FileSystem(); +var sh = fs.shell(); + +Filer.Shell.prototype.newFunction = ...; + +sh.newFunction(); +``` + The `FileSystemShell` can take an optional `options` object. The `options` object can include `env`, which is a set of environment variables. Currently supported variables include `TMP` (the path to the temporary directory), and `PATH` (the list of known paths) and @@ -1109,7 +1120,7 @@ others may be added in the future. You can also add your own, or update existing ```javascript var fs = new Filer.FileSystem(); -var sh = fs.Shell({ +var sh = fs.shell({ env: { TMP: '/tempdir', PATH: '/one:/two' @@ -1135,7 +1146,7 @@ Example: ```javascript var fs = new Filer.FileSystem(); -var sh = fs.Shell(); +var sh = fs.shell(); var p = sh.env.get('PATH'); // Store the current location @@ -1155,7 +1166,7 @@ examples below assume a `FileSystemShell` instance named `sh` has been created l ```javascript var fs = new Filer.FileSystem(); -var sh = fs.Shell(); +var sh = fs.shell(); ``` * [sh.cd(path, callback)](#cd) @@ -1360,9 +1371,9 @@ sh.tempDir(function(err, tmp) { #### sh.mkdirp(path, callback) -Recursively creates the directory at the provided path. If the +Recursively creates the directory at the provided path. If the directory already exists, no error is returned. All parents must -be valid directories (not files). +be valid directories (not files). Example: diff --git a/src/filesystem/interface.js b/src/filesystem/interface.js index 93ea6f2..e9e54e1 100644 --- a/src/filesystem/interface.js +++ b/src/filesystem/interface.js @@ -87,6 +87,9 @@ function FileSystem(options, callback) { fs.stdout = STDOUT; fs.stderr = STDERR; + // Expose Shell constructor + this.Shell = Shell.bind(undefined, this); + // Safely expose the list of open files and file // descriptor management functions var openFiles = {}; @@ -334,8 +337,4 @@ FileSystem.providers = providers; }; }); -FileSystem.prototype.Shell = function(options) { - return new Shell(this, options); -}; - module.exports = FileSystem; diff --git a/src/index.js b/src/index.js index f911644..d8e9f31 100644 --- a/src/index.js +++ b/src/index.js @@ -2,5 +2,6 @@ module.exports = { FileSystem: require('./filesystem/interface.js'), Buffer: require('./buffer.js'), Path: require('./path.js'), - Errors: require('./errors.js') + Errors: require('./errors.js'), + Shell: require('./shell/shell.js') }; diff --git a/tests/bugs/issue247.js b/tests/bugs/issue247.js index 9fa5dd1..e69a45e 100644 --- a/tests/bugs/issue247.js +++ b/tests/bugs/issue247.js @@ -8,7 +8,7 @@ describe('sh.cd doesn\'t seem to be working from a relative path if I am one or it('should properly deal with relative paths missing ./ and ../', function(done) { var fs = util.fs(); - var sh = fs.Shell(); + var sh = new fs.Shell(); sh.mkdirp('/home/scott', function(err) { if(err) throw err; diff --git a/tests/bugs/ls-depth-bug.js b/tests/bugs/ls-depth-bug.js index 3fa834b..ac2c5ae 100644 --- a/tests/bugs/ls-depth-bug.js +++ b/tests/bugs/ls-depth-bug.js @@ -9,7 +9,7 @@ describe('sh.ls and deep directory trees', function() { it('should not crash when calling sh.ls() on deep directory layouts', function(done) { var fs = util.fs(); - var sh = fs.Shell(); + var sh = new fs.Shell(); var path = ''; for(var i=0; i<50; i++) { @@ -29,7 +29,7 @@ describe('sh.ls and deep directory trees', function() { it('should not crash when calling sh.ls() on wide directory layouts', function(done) { var fs = util.fs(); - var sh = fs.Shell(); + var sh = new fs.Shell(); var dirName = '/dir'; diff --git a/tests/index.js b/tests/index.js index ff930da..e997797 100644 --- a/tests/index.js +++ b/tests/index.js @@ -38,6 +38,7 @@ require("./spec/times.spec"); require("./spec/time-flags.spec"); require("./spec/fs.watch.spec"); require("./spec/errors.spec"); +require("./spec/fs.shell.spec"); // Filer.FileSystem.providers.* require("./spec/providers/providers.spec"); diff --git a/tests/lib/test-utils.js b/tests/lib/test-utils.js index dc9e752..e8d4bde 100644 --- a/tests/lib/test-utils.js +++ b/tests/lib/test-utils.js @@ -85,7 +85,8 @@ } function shell(options) { - return fs().Shell(options); + var _fs = fs(); + return new _fs.Shell(options); } function cleanup(callback) { diff --git a/tests/spec/filer.spec.js b/tests/spec/filer.spec.js index 82ec707..82deb33 100644 --- a/tests/spec/filer.spec.js +++ b/tests/spec/filer.spec.js @@ -9,4 +9,8 @@ describe("Filer", function() { it("has FileSystem constructor", function() { expect(typeof Filer.FileSystem).to.equal('function'); }); + + it("has Shell constructor", function() { + expect(typeof Filer.Shell).to.equal('function'); + }); }); diff --git a/tests/spec/fs.shell.spec.js b/tests/spec/fs.shell.spec.js new file mode 100644 index 0000000..164e5ee --- /dev/null +++ b/tests/spec/fs.shell.spec.js @@ -0,0 +1,33 @@ +var Filer = require('../..'); +var util = require('../lib/test-utils.js'); +var expect = require('chai').expect; + +describe("fs.shell", function() { + beforeEach(util.setup); + afterEach(util.cleanup); + + it("is a function", function(done) { + var fs = util.fs(); + expect(typeof fs.Shell).to.equal('function'); + + done(); + }); + + it('should return a FileSystemShell instance', function(done) { + var fs = util.fs(); + var sh = new fs.Shell(); + + expect(sh.prototype).to.deep.equal((new Filer.Shell(fs)).prototype); + done(); + }); + + it('should reflect changes to the prototype', function(done){ + var fs = util.fs(); + var sh = new fs.Shell(); + + Filer.Shell.prototype.test = "foo"; + + expect(sh.test).to.equal("foo"); + done(); + }); +}); diff --git a/tests/spec/shell/cat.spec.js b/tests/spec/shell/cat.spec.js index 52b8841..e7b6d67 100644 --- a/tests/spec/shell/cat.spec.js +++ b/tests/spec/shell/cat.spec.js @@ -13,7 +13,7 @@ describe('FileSystemShell.cat', function() { it('should fail when files argument is absent', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.cat(null, function(error, data) { expect(error).to.exist; @@ -25,7 +25,7 @@ describe('FileSystemShell.cat', function() { it('should return the contents of a single file', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "file contents"; fs.writeFile('/file', contents, function(err) { @@ -41,7 +41,7 @@ describe('FileSystemShell.cat', function() { it('should return the contents of multiple files', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "file contents"; var contents2 = contents + '\n' + contents; @@ -62,7 +62,7 @@ describe('FileSystemShell.cat', function() { it('should fail if any of multiple file paths is invalid', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "file contents"; var contents2 = contents + '\n' + contents; diff --git a/tests/spec/shell/cd.spec.js b/tests/spec/shell/cd.spec.js index c3fc43a..c45fbf8 100644 --- a/tests/spec/shell/cd.spec.js +++ b/tests/spec/shell/cd.spec.js @@ -18,7 +18,7 @@ describe('FileSystemShell.cd', function() { it('should allow changing the path to a valid dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -34,7 +34,7 @@ describe('FileSystemShell.cd', function() { it('should fail when changing the path to an invalid dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -51,7 +51,7 @@ describe('FileSystemShell.cd', function() { it('should fail when changing the path to a file', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.writeFile('/file', 'file', function(err) { if(err) throw err; @@ -68,7 +68,7 @@ describe('FileSystemShell.cd', function() { it('should allow relative paths for a valid dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -84,7 +84,7 @@ describe('FileSystemShell.cd', function() { it('should allow .. in paths for a valid dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -111,7 +111,7 @@ describe('FileSystemShell.cd', function() { fs.symlink('/dir', '/link', function(error) { if(error) throw error; - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.cd('link', function(error) { expect(error).not.to.exist; expect(shell.pwd()).to.equal('/link'); diff --git a/tests/spec/shell/env.spec.js b/tests/spec/shell/env.spec.js index f231a08..5cf1c9e 100644 --- a/tests/spec/shell/env.spec.js +++ b/tests/spec/shell/env.spec.js @@ -34,7 +34,7 @@ describe('FileSystemShell.env', function() { it('should fail when dirs argument is absent', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.cat(null, function(error, list) { expect(error).to.exist; @@ -46,7 +46,7 @@ describe('FileSystemShell.env', function() { it('should give new value for shell.pwd() when cwd changes', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -62,7 +62,7 @@ describe('FileSystemShell.env', function() { it('should create/return the default tmp dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); expect(shell.env.get('TMP')).to.equal('/tmp'); shell.tempDir(function(err, tmp) { @@ -77,7 +77,7 @@ describe('FileSystemShell.env', function() { it('should create/return the tmp dir specified in env.TMP', function(done) { var fs = util.fs(); - var shell = fs.Shell({ + var shell = new fs.Shell({ env: { TMP: '/tempdir' } @@ -96,7 +96,7 @@ describe('FileSystemShell.env', function() { it('should allow repeated calls to tempDir()', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); expect(shell.env.get('TMP')).to.equal('/tmp'); shell.tempDir(function(err, tmp) { diff --git a/tests/spec/shell/exec.spec.js b/tests/spec/shell/exec.spec.js index 1d5c620..ee94a42 100644 --- a/tests/spec/shell/exec.spec.js +++ b/tests/spec/shell/exec.spec.js @@ -13,7 +13,7 @@ describe('FileSystemShell.exec', function() { it('should be able to execute a command .js file from the filesystem', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var cmdString = "fs.writeFile(args[0], args[1], callback);"; fs.writeFile('/cmd.js', cmdString, function(error) { diff --git a/tests/spec/shell/ls.spec.js b/tests/spec/shell/ls.spec.js index 713c96f..c9a718d 100644 --- a/tests/spec/shell/ls.spec.js +++ b/tests/spec/shell/ls.spec.js @@ -13,7 +13,7 @@ describe('FileSystemShell.ls', function() { it('should fail when dirs argument is absent', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.cat(null, function(error, list) { expect(error).to.exist; @@ -25,7 +25,7 @@ describe('FileSystemShell.ls', function() { it('should return the contents of a simple dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; var contents2 = "bb"; @@ -63,7 +63,7 @@ describe('FileSystemShell.ls', function() { it('should return the shallow contents of a dir tree', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; fs.mkdir('/dir', function(err) { @@ -119,7 +119,7 @@ describe('FileSystemShell.ls', function() { it('should return the deep contents of a dir tree', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; fs.mkdir('/dir', function(err) { diff --git a/tests/spec/shell/mkdirp.spec.js b/tests/spec/shell/mkdirp.spec.js index c9f574b..bbe6a04 100644 --- a/tests/spec/shell/mkdirp.spec.js +++ b/tests/spec/shell/mkdirp.spec.js @@ -13,7 +13,7 @@ describe('FileSystemShell.mkdirp', function() { it('should fail without a path provided', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.mkdirp(null, function(err) { expect(err).to.exist; @@ -24,7 +24,7 @@ describe('FileSystemShell.mkdirp', function() { it('should succeed if provided path is root', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.mkdirp('/', function(err) { expect(err).to.not.exist; done(); @@ -33,7 +33,7 @@ describe('FileSystemShell.mkdirp', function() { it('should succeed if the directory exists', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/test', function(err){ expect(err).to.not.exist; shell.mkdirp('/test',function(err) { @@ -45,7 +45,7 @@ describe('FileSystemShell.mkdirp', function() { it('fail if a file name is provided', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.writeFile('/test.txt', 'test', function(err){ expect(err).to.not.exist; shell.mkdirp('/test.txt', function(err) { @@ -58,7 +58,7 @@ describe('FileSystemShell.mkdirp', function() { it('should succeed on a folder on root (\'/test\')', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.mkdirp('/test', function(err) { expect(err).to.not.exist; fs.exists('/test', function(dir){ @@ -70,7 +70,7 @@ describe('FileSystemShell.mkdirp', function() { it('should succeed on a folder with a nonexistant parent (\'/test/test\')', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.mkdirp('/test/test', function(err) { expect(err).to.not.exist; fs.exists('/test', function(dir1){ @@ -85,7 +85,7 @@ describe('FileSystemShell.mkdirp', function() { it('should fail on a folder with a file for its parent (\'/test.txt/test\')', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.writeFile('/test.txt', 'test', function(err){ expect(err).to.not.exist; shell.mkdirp('/test.txt/test', function(err) { diff --git a/tests/spec/shell/rm.spec.js b/tests/spec/shell/rm.spec.js index b433655..0777460 100644 --- a/tests/spec/shell/rm.spec.js +++ b/tests/spec/shell/rm.spec.js @@ -13,7 +13,7 @@ describe('FileSystemShell.rm', function() { it('should fail when path argument is absent', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.rm(null, function(error, list) { expect(error).to.exist; @@ -25,7 +25,7 @@ describe('FileSystemShell.rm', function() { it('should remove a single file', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; fs.writeFile('/file', contents, function(err) { @@ -45,7 +45,7 @@ describe('FileSystemShell.rm', function() { it('should remove an empty dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -64,7 +64,7 @@ describe('FileSystemShell.rm', function() { it('should fail to remove a non-empty dir', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -83,7 +83,7 @@ describe('FileSystemShell.rm', function() { it('should remove a non-empty dir with option.recursive set', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); fs.mkdir('/dir', function(err) { if(err) throw err; @@ -106,7 +106,7 @@ describe('FileSystemShell.rm', function() { it('should work on a complex dir structure', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var contents = "a"; fs.mkdir('/dir', function(err) { diff --git a/tests/spec/shell/touch.spec.js b/tests/spec/shell/touch.spec.js index 73a296e..e37bd6a 100644 --- a/tests/spec/shell/touch.spec.js +++ b/tests/spec/shell/touch.spec.js @@ -20,7 +20,7 @@ describe('FileSystemShell.touch', function() { it('should create a new file if path does not exist', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.touch('/newfile', function(error) { if(error) throw error; @@ -35,7 +35,7 @@ describe('FileSystemShell.touch', function() { it('should skip creating a new file if options.updateOnly is true', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); shell.touch('/newfile', { updateOnly: true }, function(error) { if(error) throw error; @@ -49,7 +49,7 @@ describe('FileSystemShell.touch', function() { it('should update times if path does exist', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var atime = Date.parse('1 Oct 2000 15:33:22'); var mtime = Date.parse('30 Sep 2000 06:43:54'); @@ -80,7 +80,7 @@ describe('FileSystemShell.touch', function() { it('should update times to specified date if path does exist', function(done) { var fs = util.fs(); - var shell = fs.Shell(); + var shell = new fs.Shell(); var date = Date.parse('1 Oct 2001 15:33:22'); fs.open('/newfile', 'w', function (error, fd) {