| var common = require('./common'); |
| var fs = require('fs'); |
| |
| //@ |
| //@ ### touch([options,] file [, file ...]) |
| //@ ### touch([options,] file_array) |
| //@ Available options: |
| //@ |
| //@ + `-a`: Change only the access time |
| //@ + `-c`: Do not create any files |
| //@ + `-m`: Change only the modification time |
| //@ + `-d DATE`: Parse DATE and use it instead of current time |
| //@ + `-r FILE`: Use FILE's times instead of current time |
| //@ |
| //@ Examples: |
| //@ |
| //@ ```javascript |
| //@ touch('source.js'); |
| //@ touch('-c', '/path/to/some/dir/source.js'); |
| //@ touch({ '-r': FILE }, '/path/to/some/dir/source.js'); |
| //@ ``` |
| //@ |
| //@ Update the access and modification times of each FILE to the current time. |
| //@ A FILE argument that does not exist is created empty, unless -c is supplied. |
| //@ This is a partial implementation of *[touch(1)](http://linux.die.net/man/1/touch)*. |
| function _touch(opts, files) { |
| opts = common.parseOptions(opts, { |
| 'a': 'atime_only', |
| 'c': 'no_create', |
| 'd': 'date', |
| 'm': 'mtime_only', |
| 'r': 'reference', |
| }); |
| |
| if (!files) |
| common.error('no files given'); |
| else if (typeof files === 'string') |
| files = [].slice.call(arguments, 1); |
| else |
| common.error('file arg should be a string file path or an Array of string file paths'); |
| |
| files.forEach(function(f) { |
| touchFile(opts, f); |
| }); |
| return new common.ShellString('', common.state.error, common.state.errorCode); |
| } |
| |
| function touchFile(opts, file) { |
| var stat = tryStatFile(file); |
| |
| if (stat && stat.isDirectory()) { |
| // don't error just exit |
| return; |
| } |
| |
| // if the file doesn't already exist and the user has specified --no-create then |
| // this script is finished |
| if (!stat && opts.no_create) { |
| return; |
| } |
| |
| // open the file and then close it. this will create it if it doesn't exist but will |
| // not truncate the file |
| fs.closeSync(fs.openSync(file, 'a')); |
| |
| // |
| // Set timestamps |
| // |
| |
| // setup some defaults |
| var now = new Date(); |
| var mtime = opts.date || now; |
| var atime = opts.date || now; |
| |
| // use reference file |
| if (opts.reference) { |
| var refStat = tryStatFile(opts.reference); |
| if (!refStat) { |
| common.error('failed to get attributess of ' + opts.reference); |
| } |
| mtime = refStat.mtime; |
| atime = refStat.atime; |
| } else if (opts.date) { |
| mtime = opts.date; |
| atime = opts.date; |
| } |
| |
| if (opts.atime_only && opts.mtime_only) { |
| // keep the new values of mtime and atime like GNU |
| } else if (opts.atime_only) { |
| mtime = stat.mtime; |
| } else if (opts.mtime_only) { |
| atime = stat.atime; |
| } |
| |
| fs.utimesSync(file, atime, mtime); |
| } |
| |
| module.exports = _touch; |
| |
| function tryStatFile(filePath) { |
| try { |
| return fs.statSync(filePath); |
| } catch (e) { |
| return null; |
| } |
| } |