UNPKG

nx

Version:

The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.

77 lines (76 loc) 2.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.needsShellQuoting = needsShellQuoting; exports.isAlreadyQuoted = isAlreadyQuoted; exports.quoteShellArg = quoteShellArg; /** * Shell metacharacters that have special meaning and require quoting. * * Characters included: * - | - pipe * - & - background/AND * - ; - command separator * - < > - redirections * - ( ) - subshell * - $ - variable expansion * - ` - command substitution * - \ - escape * - " ' - quotes * - * ? [ ] - globbing * - { } - brace expansion * - ~ - home directory * - # - comment * - ! - history expansion * - \s - whitespace (spaces, tabs, newlines) */ const SHELL_META_CHARS = /[|&;<>()$`\\!"'*?[\]{}~#\s]/; /** * Check if a string contains shell metacharacters that require quoting. * These characters have special meaning in shell and would be interpreted * incorrectly if not quoted (e.g., | for pipe, & for background, etc.) */ function needsShellQuoting(str) { return SHELL_META_CHARS.test(str); } /** * Check if a string is already wrapped in matching quotes (single or double). */ function isAlreadyQuoted(str) { return (str.length >= 2 && ((str[0] === "'" && str[str.length - 1] === "'") || (str[0] === '"' && str[str.length - 1] === '"'))); } /** * Quote a string so it survives being interpolated into a shell command line * as a single argument. * * On Windows the safety boundary is one unbroken double-quoted run: it keeps * `^`, `&`, `|`, `<` and `>` literal through cmd.exe's parse and a `.cmd` * shim's re-parse of `%*`, but not `%`, which cmd.exe expands inside double * quotes too. * * @throws on Windows when the argument contains a double quote, which ends that * run, since cmd.exe recognizes no backslash escape. Carrying one means * caret-escaping every metacharacter instead, doubled for a `.cmd` shim, which * this path does not implement. */ function quoteShellArg(arg) { const isWindows = process.platform === 'win32'; if (isWindows && arg.includes('"')) { throw new Error(`Cannot safely pass ${arg} to cmd.exe as a single argument: a double quote inside it would end the quoting and leave the rest of the argument to be read as commands. Remove the double quote and run the command again.`); } if (arg === '') { // an unquoted empty string would vanish when joined into a command line return isWindows ? '""' : "''"; } // `^` is cmd.exe syntax rather than shell syntax, so it earns quoting only // where cmd.exe parses the command line. if (!needsShellQuoting(arg) && !(isWindows && arg.includes('^'))) { return arg; } return isWindows ? // MSVCRT reads the backslashes that precede the closing quote as escapes, // so they have to be doubled to survive as themselves. `"${arg.replace(/(\\+)$/, '$1$1')}"` : `'${arg.replace(/'/g, `'\\''`)}'`; }