123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- 'use strict';
- function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
- var fs = require('fs');
- var path = require('path');
- var which = require('which');
- var findPrefix = require('./find-prefix');
- var PATH = getPATHKey();
- var SEPARATOR = getPATHSeparator();
- /**
- * Get new $PATH setting with additional paths supplied by the npm.
- *
- * @param Object options Config options Object.
- * @param Object options.env Environment to use. Default: process.env
- * @param String options.wd Working directory. Default: process.cwd()
- * @param Function fn callback function.
- */
- function getPath(options, fn) {
- options.cwd = options.cwd || process.cwd();
- var env = options.env = options.env || process.env;
- var pathArr = getPathArr(options);
- findPrefix(options, function (err, prefixPath) {
- if (!err && prefixPath) {
- // ignore err if cannot find prefix
- pathArr.unshift(path.join(prefixPath, 'node_modules', '.bin'));
- }
- whichNpm(options, function (err, npmPath) {
- // we also unshift the bundled node-gyp-bin folder so that
- // the bundled one will be used for installing things.
- // simply ignore this step if there was no npm found
- if (err || !npmPath) {
- // ...unless npm path was explicitly passed in
- if (options.npm) {
- return fn(err || new Error('Cannot find ' + options.npm));
- }
- } else {
- pathArr.unshift(path.join(path.dirname(npmPath), 'node-gyp-bin'));
- }
- if (env[PATH]) pathArr = pathArr.concat(env[PATH].split(SEPARATOR));
- // Remove duplicated entries
- pathArr = [].concat(_toConsumableArray(new Set(pathArr)));
- fn(null, pathArr.join(SEPARATOR));
- });
- });
- }
- /**
- * Async wrapper around `getPath`.
- */
- function getPathAsync(options, fn) {
- // options is optional
- if (typeof options === 'function') {
- fn = options;
- options = {};
- }
- // if no fn, execute as sync
- if (typeof fn !== 'function') return getPathSync(options);
- options = options || {};
- options.isSync = false;
- return getPath(options, fn);
- }
- /**
- * Sync wrapper around `getPath`.
- */
- function getPathSync(options) {
- options = options || {};
- options.isSync = true;
- var thePath = null;
- // sync magic: if sync true, callback is executed sync
- // therefore we can set thePath from inside it before returning
- getPath(options, function (err, foundPath) {
- if (err) throw err;
- thePath = foundPath;
- });
- return thePath;
- }
- /**
- * Change environment to include npm path adjustments.
- *
- * @param Object options Config options Object.
- * @param Object options.env Environment to use. Default: process.env
- * @param String options.wd Working directory. Default: process.cwd()
- * @param Function fn callback function.
- */
- function setPathAsync(options, fn) {
- // options is optional
- if (typeof options === 'function') {
- fn = options;
- options = {};
- }
- // if no fn, execute as sync
- if (typeof fn !== 'function') return setPathSync(options);
- getPathAsync(options, function (err, newPath) {
- if (err) return fn(err);
- fn(null, options.env[PATH] = newPath);
- });
- }
- /**
- * Sync version of `setPathAsync`
- */
- function setPathSync(options) {
- options = options || {};
- var newPath = getPathSync(options);
- options.env[PATH] = newPath;
- return newPath;
- }
- /**
- * Generate simple parts of the npm path. Basically everything that doesn't
- * depend on potentially async operations.
- *
- * @return Array
- */
- function getPathArr(options) {
- var wd = options.cwd;
- var pathArr = [];
- var p = wd.split(path.sep + 'node_modules' + path.sep);
- var acc = path.resolve(p.shift());
- // first add the directory containing the `node` executable currently
- // running, so that any lifecycle script that invoke 'node' will execute
- // this same one.
- pathArr.unshift(path.dirname(process.execPath));
- p.forEach(function (pp) {
- pathArr.unshift(path.join(acc, 'node_modules', '.bin'));
- acc = path.join(acc, 'node_modules', pp);
- });
- pathArr.unshift(path.join(acc, 'node_modules', '.bin'));
- return pathArr;
- }
- /**
- * Use callback-style signature but toggle sync execution if `isSync` is true.
- * If options.npm is supplied, this will simply provide npm/bin/npm-cli.
- */
- function whichNpm(options, fn) {
- var npmCli = options.npm && path.join(options.npm, 'bin', 'npm-cli.js');
- if (options.isSync) {
- var npmPath = null;
- try {
- npmPath = fs.realpathSync(npmCli || which.sync('npm'));
- } catch (err) {
- return fn(err);
- }
- fn(null, npmPath);
- return;
- }
- if (options.npm) {
- fs.realpath(npmCli, fn);
- return;
- }
- which('npm', function (err, npmPath) {
- if (err) return fn(err);
- fs.realpath(npmPath, fn);
- });
- }
- /**
- * Get key to use as $PATH in environment
- */
- function getPATHKey() {
- var PATH = 'PATH';
- // windows calls it's path 'Path' usually, but this is not guaranteed.
- if (process.platform === 'win32') {
- PATH = 'Path';
- Object.keys(process.env).forEach(function (e) {
- if (e.match(/^PATH$/i)) {
- PATH = e;
- }
- });
- }
- return PATH;
- }
- /**
- * Get $PATH separator based on environment
- */
- function getPATHSeparator() {
- return process.platform === 'win32' ? ';' : ':';
- }
- module.exports = setPathAsync;
- module.exports.get = getPathAsync;
- module.exports.get.sync = getPathSync;
- module.exports.getSync = getPathSync;
- module.exports.set = setPathAsync;
- module.exports.set.sync = setPathSync;
- module.exports.setSync = setPathSync;
- module.exports.PATH = PATH;
- module.exports.SEPARATOR = SEPARATOR;
|