diff --git a/index.js b/index.js index 8c7d4f8d8..a292dca5e 100644 --- a/index.js +++ b/index.js @@ -481,30 +481,48 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) { // executable var f = argv[1]; - var link = readlink(f); + // name of the subcommand, link `pm-install` + var bin = basename(f, '.js') + '-' + args[0]; + + + // In case of globally installed, get the base dir where executable + // subcommand file should be located at + var baseDir + , link = readlink(f); + + // when symbolink is relative path if (link !== f && link.charAt(0) !== '/') { link = path.join(dirname(f), link) } - var dir = dirname(link); - var bin = basename(f, '.js') + '-' + args[0]; + baseDir = dirname(link); // prefer local `./` to bin in the $PATH - var local = path.join(dir, bin); - try { - // for versions before node v0.8 when there weren't `fs.existsSync` - if (fs.statSync(local).isFile()) { - bin = local; - } - } catch (e) {} + var localBin = path.join(baseDir, bin); + + // whether bin file is a js script with explicit `.js` extension + var isExplicitJS = false; + if (exists(localBin + '.js')) { + bin = localBin + '.js'; + isExplicitJS = true; + } else if (exists(localBin)) { + bin = localBin; + } - // run it args = args.slice(1); var proc; if (process.platform !== 'win32') { - proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] }); + if (isExplicitJS) { + args.unshift(localBin); + // add executable arguments to spawn + args = process.execArgv.concat(args); + + proc = spawn('node', args, { stdio: 'inherit', customFds: [0, 1, 2] }); + } else { + proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] }); + } } else { - args.unshift(local); + args.unshift(localBin); proc = spawn(process.execPath, args, { stdio: 'inherit'}); } @@ -1081,3 +1099,15 @@ function humanReadableArgName(arg) { ? '<' + nameOutput + '>' : '[' + nameOutput + ']' } + +// for versions before node v0.8 when there weren't `fs.existsSync` +function exists(file) { + try { + if (fs.statSync(file).isFile()) { + return true; + } + } catch (e) { + return false; + } +} + diff --git a/test/fixtures/pm b/test/fixtures/pm index 66f8b6dca..c64db2513 100755 --- a/test/fixtures/pm +++ b/test/fixtures/pm @@ -7,4 +7,5 @@ program .command('install [name]', 'install one or more packages') .command('search [query]', 'search with optional query') .command('list', 'list packages installed') + .command('publish', 'publish or update package') .parse(process.argv); diff --git a/test/fixtures/pm-publish.js b/test/fixtures/pm-publish.js new file mode 100644 index 000000000..1c21a0147 --- /dev/null +++ b/test/fixtures/pm-publish.js @@ -0,0 +1,2 @@ +console.log('publish'); + diff --git a/test/test.command.executableSubcommand.js b/test/test.command.executableSubcommand.js index 1f36d320d..2dae6b7bf 100644 --- a/test/test.command.executableSubcommand.js +++ b/test/test.command.executableSubcommand.js @@ -17,6 +17,11 @@ exec(bin + ' install', function (error, stdout, stderr) { stdout.should.equal('install\n'); }); +// subcommand bin file with explicit extension +exec(bin + ' publish', function (error, stdout, stderr) { + stdout.should.equal('publish\n'); +}); + // spawn EACCES exec(bin + ' search', function (error, stdout, stderr) { // TODO error info are not the same in between