diff options
Diffstat (limited to 'node_modules/bin-links/lib/link-gently.js')
-rw-r--r-- | node_modules/bin-links/lib/link-gently.js | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/node_modules/bin-links/lib/link-gently.js b/node_modules/bin-links/lib/link-gently.js new file mode 100644 index 000000000..75b157618 --- /dev/null +++ b/node_modules/bin-links/lib/link-gently.js @@ -0,0 +1,57 @@ +// if the thing isn't there, skip it +// if there's a non-symlink there already, eexist +// if there's a symlink already, pointing somewhere else, eexist +// if there's a symlink already, pointing into our pkg, remove it first +// then create the symlink + +const { promisify } = require('util') +const { resolve, dirname } = require('path') +const mkdirp = require('mkdirp-infer-owner') +const fs = require('fs') +const symlink = promisify(fs.symlink) +const readlink = promisify(fs.readlink) +const lstat = promisify(fs.lstat) +const throwNonEnoent = er => { if (er.code !== 'ENOENT') throw er } + +// disable glob in our rimraf calls +const rimraf = promisify(require('rimraf')) +const rm = path => rimraf(path, { glob: false }) + +const SKIP = Symbol('skip - missing or already installed') + +const linkGently = ({path, to, from, absFrom, force}) => { + // if the script or manpage isn't there, just ignore it. + // this arguably *should* be an install error of some sort, + // or at least a warning, but npm has always behaved this + // way in the past, so it'd be a breaking change + return Promise.all([ + lstat(absFrom).catch(throwNonEnoent), + lstat(to).catch(throwNonEnoent), + ]).then(([stFrom, stTo]) => { + // not present in package, skip it + if (!stFrom) + return SKIP + + // exists! maybe clobber if we can + if (stTo) { + if (!stTo.isSymbolicLink()) + return force ? rm(to) : Promise.resolve() + + return readlink(to).then(target => { + if (target === from) + return SKIP // skip it, already set up like we want it. + + target = resolve(dirname(to), target) + if (target.indexOf(path) === 0 || force) + return rm(to) + }) + } else { + // doesn't exist, dir might not either + return mkdirp(dirname(to)) + } + }) + // this will fail if we didn't remove it + .then(skip => skip !== SKIP && symlink(from, to, 'file').then(() => true)) +} + +module.exports = linkGently |