aboutsummaryrefslogtreecommitdiff
path: root/node_modules/touch
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/touch')
-rw-r--r--node_modules/touch/LICENSE15
-rw-r--r--node_modules/touch/README.md52
-rwxr-xr-xnode_modules/touch/bin/nodetouch.js112
-rw-r--r--node_modules/touch/index.js224
-rw-r--r--node_modules/touch/package.json28
5 files changed, 431 insertions, 0 deletions
diff --git a/node_modules/touch/LICENSE b/node_modules/touch/LICENSE
new file mode 100644
index 0000000..05eeeb8
--- /dev/null
+++ b/node_modules/touch/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/node_modules/touch/README.md b/node_modules/touch/README.md
new file mode 100644
index 0000000..b5a361e
--- /dev/null
+++ b/node_modules/touch/README.md
@@ -0,0 +1,52 @@
+# node-touch
+
+For all your node touching needs.
+
+## Installing
+
+```bash
+npm install touch
+```
+
+## CLI Usage:
+
+See `man touch`
+
+This package exports a binary called `nodetouch` that works mostly
+like the unix builtin `touch(1)`.
+
+## API Usage:
+
+```javascript
+var touch = require("touch")
+```
+
+Gives you the following functions:
+
+* `touch(filename, options, cb)`
+* `touch.sync(filename, options)`
+* `touch.ftouch(fd, options, cb)`
+* `touch.ftouchSync(fd, options)`
+
+All the `options` objects are optional.
+
+All the async functions return a Promise. If a callback function is
+provided, then it's attached to the Promise.
+
+## Options
+
+* `force` like `touch -f` Boolean
+* `time` like `touch -t <date>` Can be a Date object, or any parseable
+ Date string, or epoch ms number.
+* `atime` like `touch -a` Can be either a Boolean, or a Date.
+* `mtime` like `touch -m` Can be either a Boolean, or a Date.
+* `ref` like `touch -r <file>` Must be path to a file.
+* `nocreate` like `touch -c` Boolean
+
+If neither `atime` nor `mtime` are set, then both values are set. If
+one of them is set, then the other is not.
+
+## cli
+
+This package creates a `nodetouch` command line executable that works
+very much like the unix builtin `touch(1)`
diff --git a/node_modules/touch/bin/nodetouch.js b/node_modules/touch/bin/nodetouch.js
new file mode 100755
index 0000000..f78f082
--- /dev/null
+++ b/node_modules/touch/bin/nodetouch.js
@@ -0,0 +1,112 @@
+#!/usr/bin/env node
+const touch = require("../index.js")
+
+const usage = code => {
+ console[code ? 'error' : 'log'](
+ 'usage:\n' +
+ 'touch [-acfm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...'
+ )
+ process.exit(code)
+}
+
+const singleFlags = {
+ a: 'atime',
+ m: 'mtime',
+ c: 'nocreate',
+ f: 'force'
+}
+
+const singleOpts = {
+ r: 'ref',
+ t: 'time'
+}
+
+const files = []
+const args = process.argv.slice(2)
+const options = {}
+for (let i = 0; i < args.length; i++) {
+ const arg = args[i]
+ if (!arg.match(/^-/)) {
+ files.push(arg)
+ continue
+ }
+
+ // expand shorthands
+ if (arg.charAt(1) !== '-') {
+ const expand = []
+ for (let f = 1; f < arg.length; f++) {
+ const fc = arg.charAt(f)
+ const sf = singleFlags[fc]
+ const so = singleOpts[fc]
+ if (sf)
+ expand.push('--' + sf)
+ else if (so) {
+ const soslice = arg.slice(f + 1)
+ const soval = soslice.charAt(0) === '=' ? soslice : '=' + soslice
+ expand.push('--' + so + soval)
+ f = arg.length
+ } else if (arg !== '-' + fc)
+ expand.push('-' + fc)
+ }
+ if (expand.length) {
+ args.splice.apply(args, [i, 1].concat(expand))
+ i--
+ continue
+ }
+ }
+
+ const argsplit = arg.split('=')
+ const key = argsplit.shift().replace(/^\-\-/, '')
+ const val = argsplit.length ? argsplit.join('=') : null
+
+ switch (key) {
+ case 'time':
+ const timestr = val || args[++i]
+ // [-t [[CC]YY]MMDDhhmm[.SS]]
+ const parsedtime = timestr.match(
+ /^(([0-9]{2})?([0-9]{2}))?([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})(\.([0-9]{2}))?$/
+ )
+ if (!parsedtime) {
+ console.error('touch: out of range or illegal ' +
+ 'time specification: ' +
+ '[[CC]YY]MMDDhhmm[.SS]')
+ process.exit(1)
+ } else {
+ const y = +parsedtime[1]
+ const year = parsedtime[2] ? y
+ : y <= 68 ? 2000 + y
+ : 1900 + y
+
+ const MM = +parsedtime[4] - 1
+ const dd = +parsedtime[5]
+ const hh = +parsedtime[6]
+ const mm = +parsedtime[7]
+ const ss = +parsedtime[8]
+
+ options.time = new Date(Date.UTC(year, MM, dd, hh, mm, ss))
+ }
+ continue
+
+ case 'ref':
+ options.ref = val || args[++i]
+ continue
+
+ case 'mtime':
+ case 'nocreate':
+ case 'atime':
+ case 'force':
+ options[key] = true
+ continue
+
+ default:
+ console.error('touch: illegal option -- ' + arg)
+ usage(1)
+ }
+}
+
+if (!files.length)
+ usage()
+
+process.exitCode = 0
+Promise.all(files.map(f => touch(f, options)))
+ .catch(er => process.exitCode = 1)
diff --git a/node_modules/touch/index.js b/node_modules/touch/index.js
new file mode 100644
index 0000000..f942e42
--- /dev/null
+++ b/node_modules/touch/index.js
@@ -0,0 +1,224 @@
+'use strict'
+
+const EE = require('events').EventEmitter
+const cons = require('constants')
+const fs = require('fs')
+
+module.exports = (f, options, cb) => {
+ if (typeof options === 'function')
+ cb = options, options = {}
+
+ const p = new Promise((res, rej) => {
+ new Touch(validOpts(options, f, null))
+ .on('done', res).on('error', rej)
+ })
+
+ return cb ? p.then(res => cb(null, res), cb) : p
+}
+
+module.exports.sync = module.exports.touchSync = (f, options) =>
+ (new TouchSync(validOpts(options, f, null)), undefined)
+
+module.exports.ftouch = (fd, options, cb) => {
+ if (typeof options === 'function')
+ cb = options, options = {}
+
+ const p = new Promise((res, rej) => {
+ new Touch(validOpts(options, null, fd))
+ .on('done', res).on('error', rej)
+ })
+
+ return cb ? p.then(res => cb(null, res), cb) : p
+}
+
+module.exports.ftouchSync = (fd, opt) =>
+ (new TouchSync(validOpts(opt, null, fd)), undefined)
+
+const validOpts = (options, path, fd) => {
+ options = Object.create(options || {})
+ options.fd = fd
+ options.path = path
+
+ // {mtime: true}, {ctime: true}
+ // If set to something else, then treat as epoch ms value
+ const now = parseInt(new Date(options.time || Date.now()).getTime() / 1000)
+ if (!options.atime && !options.mtime)
+ options.atime = options.mtime = now
+ else {
+ if (true === options.atime)
+ options.atime = now
+
+ if (true === options.mtime)
+ options.mtime = now
+ }
+
+ let oflags = 0
+ if (!options.force)
+ oflags = oflags | cons.O_RDWR
+
+ if (!options.nocreate)
+ oflags = oflags | cons.O_CREAT
+
+ options.oflags = oflags
+ return options
+}
+
+class Touch extends EE {
+ constructor (options) {
+ super(options)
+ this.fd = options.fd
+ this.path = options.path
+ this.atime = options.atime
+ this.mtime = options.mtime
+ this.ref = options.ref
+ this.nocreate = !!options.nocreate
+ this.force = !!options.force
+ this.closeAfter = options.closeAfter
+ this.oflags = options.oflags
+ this.options = options
+
+ if (typeof this.fd !== 'number') {
+ this.closeAfter = true
+ this.open()
+ } else
+ this.onopen(null, this.fd)
+ }
+
+ emit (ev, data) {
+ // we only emit when either done or erroring
+ // in both cases, need to close
+ this.close()
+ return super.emit(ev, data)
+ }
+
+ close () {
+ if (typeof this.fd === 'number' && this.closeAfter)
+ fs.close(this.fd, () => {})
+ }
+
+ open () {
+ fs.open(this.path, this.oflags, (er, fd) => this.onopen(er, fd))
+ }
+
+ onopen (er, fd) {
+ if (er) {
+ if (er.code === 'EISDIR')
+ this.onopen(null, null)
+ else if (er.code === 'ENOENT' && this.nocreate)
+ this.emit('done')
+ else
+ this.emit('error', er)
+ } else {
+ this.fd = fd
+ if (this.ref)
+ this.statref()
+ else if (!this.atime || !this.mtime)
+ this.fstat()
+ else
+ this.futimes()
+ }
+ }
+
+ statref () {
+ fs.stat(this.ref, (er, st) => {
+ if (er)
+ this.emit('error', er)
+ else
+ this.onstatref(st)
+ })
+ }
+
+ onstatref (st) {
+ this.atime = this.atime && parseInt(st.atime.getTime()/1000, 10)
+ this.mtime = this.mtime && parseInt(st.mtime.getTime()/1000, 10)
+ if (!this.atime || !this.mtime)
+ this.fstat()
+ else
+ this.futimes()
+ }
+
+ fstat () {
+ const stat = this.fd ? 'fstat' : 'stat'
+ const target = this.fd || this.path
+ fs[stat](target, (er, st) => {
+ if (er)
+ this.emit('error', er)
+ else
+ this.onfstat(st)
+ })
+ }
+
+ onfstat (st) {
+ if (typeof this.atime !== 'number')
+ this.atime = parseInt(st.atime.getTime()/1000, 10)
+
+ if (typeof this.mtime !== 'number')
+ this.mtime = parseInt(st.mtime.getTime()/1000, 10)
+
+ this.futimes()
+ }
+
+ futimes () {
+ const utimes = this.fd ? 'futimes' : 'utimes'
+ const target = this.fd || this.path
+ fs[utimes](target, ''+this.atime, ''+this.mtime, er => {
+ if (er)
+ this.emit('error', er)
+ else
+ this.emit('done')
+ })
+ }
+}
+
+class TouchSync extends Touch {
+ open () {
+ try {
+ this.onopen(null, fs.openSync(this.path, this.oflags))
+ } catch (er) {
+ this.onopen(er)
+ }
+ }
+
+ statref () {
+ let threw = true
+ try {
+ this.onstatref(fs.statSync(this.ref))
+ threw = false
+ } finally {
+ if (threw)
+ this.close()
+ }
+ }
+
+ fstat () {
+ let threw = true
+ const stat = this.fd ? 'fstatSync' : 'statSync'
+ const target = this.fd || this.path
+ try {
+ this.onfstat(fs[stat](target))
+ threw = false
+ } finally {
+ if (threw)
+ this.close()
+ }
+ }
+
+ futimes () {
+ let threw = true
+ const utimes = this.fd ? 'futimesSync' : 'utimesSync'
+ const target = this.fd || this.path
+ try {
+ fs[utimes](target, this.atime, this.mtime)
+ threw = false
+ } finally {
+ if (threw)
+ this.close()
+ }
+ this.emit('done')
+ }
+
+ close () {
+ if (typeof this.fd === 'number' && this.closeAfter)
+ try { fs.closeSync(this.fd) } catch (er) {}
+ }
+}
diff --git a/node_modules/touch/package.json b/node_modules/touch/package.json
new file mode 100644
index 0000000..05608de
--- /dev/null
+++ b/node_modules/touch/package.json
@@ -0,0 +1,28 @@
+{
+ "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
+ "name": "touch",
+ "description": "like touch(1) in node",
+ "version": "3.1.0",
+ "repository": "git://github.com/isaacs/node-touch.git",
+ "bin": {
+ "nodetouch": "./bin/nodetouch.js"
+ },
+ "dependencies": {
+ "nopt": "~1.0.10"
+ },
+ "license": "ISC",
+ "scripts": {
+ "test": "tap test/*.js --100 -J",
+ "preversion": "npm test",
+ "postversion": "npm publish",
+ "postpublish": "git push origin --all; git push origin --tags"
+ },
+ "devDependencies": {
+ "mutate-fs": "^1.1.0",
+ "tap": "^10.7.0"
+ },
+ "files": [
+ "index.js",
+ "bin/nodetouch.js"
+ ]
+}