mirror of
https://github.com/pnpm/pnpm.git
synced 2026-02-05 12:41:44 -05:00
Merge pull request #245 from zkochan/issue244
Preserve symlinks on Node.js >=v6.3.0
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
var join = require('path').join
|
||||
var basename = require('path').basename
|
||||
var semver = require('semver')
|
||||
var relSymlink = require('../fs/rel_symlink')
|
||||
var fs = require('mz/fs')
|
||||
var mkdirp = require('../fs/mkdirp')
|
||||
var debug = require('debug')('pnpm:link_bins')
|
||||
var requireJson = require('../fs/require_json')
|
||||
|
||||
var preserveSymlinks = semver.satisfies(process.version, '>=6.3.0')
|
||||
|
||||
module.exports = function linkAllBins (modules) {
|
||||
getDirectories(modules)
|
||||
.reduce((pkgDirs, dir) => pkgDirs.concat(isScopedPkgsDir(dir) ? getDirectories(dir) : dir), [])
|
||||
@@ -38,25 +41,88 @@ function isScopedPkgsDir (dirPath) {
|
||||
|
||||
function linkBins (modules, target) {
|
||||
var pkg = tryRequire(join(target, 'package.json'))
|
||||
|
||||
if (!pkg || !pkg.bin) return
|
||||
|
||||
var bins = binify(pkg)
|
||||
|
||||
return Object.keys(bins).map(bin => {
|
||||
var actualBin = bins[bin]
|
||||
var externalBinPath = join(modules, '.bin', bin)
|
||||
|
||||
return Promise.resolve()
|
||||
.then(_ => fs.chmod(join(target, actualBin), 0o755))
|
||||
.then(_ => mkdirp(join(modules, '.bin')))
|
||||
.then(_ => debug('linking %s -> %s',
|
||||
join(target, actualBin),
|
||||
join(modules, '.bin', bin)))
|
||||
.then(_ => relSymlink(
|
||||
join(target, actualBin),
|
||||
join(modules, '.bin', bin)))
|
||||
.then(_ => {
|
||||
if (!preserveSymlinks) {
|
||||
return makeExecutable(join(target, actualBin))
|
||||
.then(_ => debug('linking %s -> %s',
|
||||
join(target, actualBin),
|
||||
externalBinPath))
|
||||
.then(_ => relSymlink(
|
||||
join(target, actualBin),
|
||||
externalBinPath))
|
||||
}
|
||||
|
||||
var targetPath = join(pkg.name, actualBin)
|
||||
if (process.platform !== 'win32') {
|
||||
return proxy(externalBinPath, targetPath)
|
||||
}
|
||||
return cmdShim(externalBinPath, targetPath)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function makeExecutable (filePath) {
|
||||
return fs.chmod(filePath, 0o755)
|
||||
}
|
||||
|
||||
function proxy (proxyPath, targetPath) {
|
||||
var proxyContent = [
|
||||
'#!/bin/sh',
|
||||
'":" //# comment; exec /usr/bin/env node --preserve-symlinks "$0" "$@"',
|
||||
"require('../" + targetPath + "')"
|
||||
].join('\n')
|
||||
fs.writeFileSync(proxyPath, proxyContent, 'utf8')
|
||||
return makeExecutable(proxyPath)
|
||||
}
|
||||
|
||||
function cmdShim (proxyPath, targetPath) {
|
||||
var cmdContent = [
|
||||
'@IF EXIST "%~dp0\\node.exe" (',
|
||||
' "%~dp0\\node.exe --preserve-symlinks" "%~dp0/../' + targetPath + '" %*',
|
||||
') ELSE (',
|
||||
' @SETLOCAL',
|
||||
' @SET PATHEXT=%PATHEXT:;.JS;=;%',
|
||||
' node --preserve-symlinks "%~dp0/../' + targetPath + '" %*',
|
||||
')'
|
||||
].join('\n')
|
||||
fs.writeFileSync(proxyPath + '.cmd', cmdContent, 'utf8')
|
||||
|
||||
var shContent = [
|
||||
'#!/bin/sh',
|
||||
'basedir=$(dirname "$(echo "$0" | sed -e \'s,\\,/,g\')")',
|
||||
'',
|
||||
'case `uname` in',
|
||||
' *CYGWIN*) basedir=`cygpath -w "$basedir"`;;',
|
||||
'esac',
|
||||
'',
|
||||
'if [ -x "$basedir/node" ]; then',
|
||||
' "$basedir/node --preserve-symlinks" "$basedir/../' + targetPath + '" "$@"',
|
||||
' ret=$?',
|
||||
'else ',
|
||||
' node --preserve-symlinks "$basedir/../' + targetPath + '" "$@"',
|
||||
' ret=$?',
|
||||
'fi',
|
||||
'exit $ret',
|
||||
''
|
||||
].join('\n')
|
||||
fs.writeFileSync(proxyPath, shContent, 'utf8')
|
||||
return Promise.all([
|
||||
makeExecutable(proxyPath + '.cmd'),
|
||||
makeExecutable(proxyPath)
|
||||
])
|
||||
}
|
||||
|
||||
/*
|
||||
* Like `require()`, but returns `undefined` when it fails
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user