diff --git a/src/shell.js b/src/shell.js index 48eb925..c1f18b5 100644 --- a/src/shell.js +++ b/src/shell.js @@ -1,5 +1,9 @@ define(function(require) { + var Path = require('src/path'); + + + function Shell(fs, options) { options = options || {}; @@ -43,8 +47,19 @@ define(function(require) { }; + /** + * Create a file if it does not exist, or update access and + * modified times if it does. Valid options include: + * + * * create - whether to create the file if missing (defaults to true) + * * date - use the provided Date value instead of current date/time + */ Shell.prototype.touch = function(path, options, callback) { var fs = this.fs; + if(typeof options === 'function') { + callback = options; + options = {}; + } path = Path.resolve(this.cwd, path); function createFile(path) { @@ -55,14 +70,22 @@ define(function(require) { function updateTimes(path) { var now = Date.now(); - fs.utimes(path, now, now, function(error) { + var atime = options.date || now; + var mtime = options.date || now; + + fs.utimes(path, atime, mtime, function(error) { callback(error); }); } fs.stat(path, function(error, stats) { if(error) { - createFile(path); + // Skip file creation if create is `false` + if(options.create === false) { + callback(); + } else { + createFile(path); + } } else { updateTimes(path); } diff --git a/tests/lib/test-utils.js b/tests/lib/test-utils.js index 666a2f2..bca7658 100644 --- a/tests/lib/test-utils.js +++ b/tests/lib/test-utils.js @@ -68,6 +68,10 @@ function(Filer, IndexedDBTestProvider, WebSQLTestProvider, MemoryTestProvider) { return _provider; } + function shell() { + return fs().Shell(); + } + function cleanup(callback) { if(!_provider) { return; @@ -100,6 +104,7 @@ function(Filer, IndexedDBTestProvider, WebSQLTestProvider, MemoryTestProvider) { uniqueName: uniqueName, setup: setup, fs: fs, + shell: shell, provider: provider, providers: { IndexedDB: IndexedDBTestProvider, diff --git a/tests/spec/shell/touch.spec.js b/tests/spec/shell/touch.spec.js new file mode 100644 index 0000000..ba86827 --- /dev/null +++ b/tests/spec/shell/touch.spec.js @@ -0,0 +1,104 @@ +define(["Filer", "util"], function(Filer, util) { + + function getTimes(fs, path, callback) { + fs.stat(path, function(error, stats) { + if(error) throw error; + callback({mtime: stats.mtime, atime: stats.atime}); + }); + } + + describe('FileSystemShell.touch', function() { + beforeEach(util.setup); + afterEach(util.cleanup); + + it('should be a function', function() { + var shell = util.shell(); + expect(shell.touch).to.be.a('function'); + }); + + it('should create a new file if path does not exist', function(done) { + var fs = util.fs(); + var shell = fs.Shell(); + + shell.touch('/newfile', function(error) { + if(error) throw error; + + fs.stat('/newfile', function(error, stats) { + expect(error).not.to.exist; + expect(stats.type).to.equal('FILE'); + done(); + }); + }); + }); + + it('should skip creating a new file if options.create is false', function(done) { + var fs = util.fs(); + var shell = fs.Shell(); + + shell.touch('/newfile', { create: false }, function(error) { + if(error) throw error; + + fs.stat('/newfile', function(error, stats) { + expect(error).to.exist; + done(); + }); + }); + }); + + it('should update times if path does exist', function(done) { + var fs = util.fs(); + var shell = fs.Shell(); + var atime = Date.parse('1 Oct 2000 15:33:22'); + var mtime = Date.parse('30 Sep 2000 06:43:54'); + + fs.open('/newfile', 'w', function (error, fd) { + if (error) throw error; + + fs.futimes(fd, atime, mtime, function (error) { + if(error) throw error; + + fs.close(fd, function(error) { + if(error) throw error; + + getTimes(fs, '/newfile', function(times1) { + shell.touch('/newfile', function(error) { + expect(error).not.to.exist; + + getTimes(fs, '/newfile', function(times2) { + expect(times2.mtime).to.be.above(times1.mtime); + expect(times2.atime).to.be.above(times1.atime); + done(); + }); + }); + }); + }); + }); + }); + }); + + it('should update times to specified date if path does exist', function(done) { + var fs = util.fs(); + var shell = fs.Shell(); + var date = Date.parse('1 Oct 2001 15:33:22'); + + fs.open('/newfile', 'w', function (error, fd) { + if (error) throw error; + + fs.close(fd, function(error) { + if(error) throw error; + + shell.touch('/newfile', { date: date }, function(error) { + expect(error).not.to.exist; + + getTimes(fs, '/newfile', function(times) { + expect(times.mtime).to.equal(date); + expect(times.atime).to.equal(date); + done(); + }); + }); + }); + }); + }); + }); + +}); diff --git a/tests/test-manifest.js b/tests/test-manifest.js index 73e8ae5..f7f77e4 100644 --- a/tests/test-manifest.js +++ b/tests/test-manifest.js @@ -42,6 +42,9 @@ define([ "spec/adapters/adapters.spec", "spec/adapters/adapters.general.spec", + // Filer.FileSystemShell.* + "spec/shell/touch.spec", + // Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test) "spec/node-js/simple/test-fs-mkdir", "spec/node-js/simple/test-fs-null-bytes",