From 12d8f7fab0875af1e05a91dd5945e05c5350a6d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Thu, 26 Apr 2018 18:45:12 +0100 Subject: [PATCH] feat(bin): Implement an optional parameter support to `yarn bin` (#5739) * feat(bin): Implement an optional parameter support to `yarn bin` This allows to get the path to a binary without making assumptions regarding the layout of the `node_modules` folder. BREAKING CHANGE: n/a n/a * Adds `yarn bin` tests * Update en.js * Update bin.js * Update bin.js * Fixes the tests --- __tests__/commands/bin.js | 26 ++++++++++++++++++++++++++ src/cli/commands/bin.js | 13 ++++++++++++- src/reporters/lang/en.js | 1 + 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 __tests__/commands/bin.js diff --git a/__tests__/commands/bin.js b/__tests__/commands/bin.js new file mode 100644 index 0000000000..56730ab9dc --- /dev/null +++ b/__tests__/commands/bin.js @@ -0,0 +1,26 @@ +/* @flow */ + +import {run as buildRun, runInstall} from './_helpers.js'; +import {BufferReporter} from '../../src/reporters/index.js'; +import {run} from '../../src/cli/commands/bin.js'; + +const path = require('path'); + +const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'bin'); +const runBin = buildRun.bind(null, BufferReporter, fixturesLoc, (args, flags, config, reporter): Promise => { + return run(config, reporter, flags, args); +}); + +test('running bin without arguments should return the folder where the binaries are stored', (): Promise => { + return runBin([], {}, '../install/install-production-bin', (config, reporter): ?Promise => { + expect(reporter.getBufferText()).toMatch(/[\\\/]node_modules[\\\/]\.bin[\\\/]?$/); + }); +}); + +test('running bin with a binary name as the argument should return its full path', (): Promise => { + return runInstall({binLinks: true}, 'install-production-bin', async (config): ?Promise => { + const reporter = new BufferReporter(); + await run(config, reporter, {}, ['rimraf']); + expect(reporter.getBufferText()).toMatch(/[\\\/]node_modules[\\\/]\.bin[\\\/]rimraf$/); + }); +}); diff --git a/src/cli/commands/bin.js b/src/cli/commands/bin.js index 033b6ce002..3f1db7d1ff 100644 --- a/src/cli/commands/bin.js +++ b/src/cli/commands/bin.js @@ -4,6 +4,7 @@ import type {Reporter} from '../../reporters/index.js'; import type Config from '../../config.js'; import RegistryYarn from '../../resolvers/registries/yarn-resolver.js'; +const fs = require('fs'); const path = require('path'); export function hasWrapper(commander: Object): boolean { @@ -16,6 +17,16 @@ export function setFlags(commander: Object) { export function run(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { const binFolder = path.join(config.cwd, config.registries[RegistryYarn.registry].folder, '.bin'); - reporter.log(binFolder, {force: true}); + if (args.length === 0) { + reporter.log(binFolder, {force: true}); + } else { + const binName = args[0]; + const finalPath = path.normalize(`${binFolder}/${binName}`); + if (fs.existsSync(finalPath)) { + reporter.log(finalPath, {force: true}); + } else { + reporter.error(reporter.lang('packageBinaryNotFound', binName)); + } + } return Promise.resolve(); } diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index 97429eb895..f6f585f07e 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -356,6 +356,7 @@ const messages = { packageInstalledWithBinaries: 'Installed $0 with binaries:', packageHasBinaries: '$0 has binaries:', packageHasNoBinaries: '$0 has no binaries', + packageBinaryNotFound: "Couldn't find a binary named $0", couldBeDeduped: '$0 could be deduped from $1 to $2', lockfileNotContainPattern: 'Lockfile does not contain pattern: $0',