Permalink
Cannot retrieve contributors at this time
309 lines (259 sloc)
7.71 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/execa/index.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Buffer} from 'node:buffer'; | |
import path from 'node:path'; | |
import childProcess from 'node:child_process'; | |
import process from 'node:process'; | |
import crossSpawn from 'cross-spawn'; | |
import stripFinalNewline from 'strip-final-newline'; | |
import {npmRunPathEnv} from 'npm-run-path'; | |
import onetime from 'onetime'; | |
import {makeError} from './lib/error.js'; | |
import {normalizeStdio, normalizeStdioNode} from './lib/stdio.js'; | |
import {spawnedKill, spawnedCancel, setupTimeout, validateTimeout, setExitHandler} from './lib/kill.js'; | |
import {addPipeMethods} from './lib/pipe.js'; | |
import {handleInput, getSpawnedResult, makeAllStream, handleInputSync} from './lib/stream.js'; | |
import {mergePromise, getSpawnedPromise} from './lib/promise.js'; | |
import {joinCommand, parseCommand, parseTemplates, getEscapedCommand} from './lib/command.js'; | |
import {logCommand, verboseDefault} from './lib/verbose.js'; | |
const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; | |
const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => { | |
const env = extendEnv ? {...process.env, ...envOption} : envOption; | |
if (preferLocal) { | |
return npmRunPathEnv({env, cwd: localDir, execPath}); | |
} | |
return env; | |
}; | |
const handleArguments = (file, args, options = {}) => { | |
const parsed = crossSpawn._parse(file, args, options); | |
file = parsed.command; | |
args = parsed.args; | |
options = parsed.options; | |
options = { | |
maxBuffer: DEFAULT_MAX_BUFFER, | |
buffer: true, | |
stripFinalNewline: true, | |
extendEnv: true, | |
preferLocal: false, | |
localDir: options.cwd || process.cwd(), | |
execPath: process.execPath, | |
encoding: 'utf8', | |
reject: true, | |
cleanup: true, | |
all: false, | |
windowsHide: true, | |
verbose: verboseDefault, | |
...options, | |
}; | |
options.env = getEnv(options); | |
options.stdio = normalizeStdio(options); | |
if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') { | |
// #116 | |
args.unshift('/q'); | |
} | |
return {file, args, options, parsed}; | |
}; | |
const handleOutput = (options, value, error) => { | |
if (typeof value !== 'string' && !Buffer.isBuffer(value)) { | |
// When `execaSync()` errors, we normalize it to '' to mimic `execa()` | |
return error === undefined ? undefined : ''; | |
} | |
if (options.stripFinalNewline) { | |
return stripFinalNewline(value); | |
} | |
return value; | |
}; | |
export function execa(file, args, options) { | |
const parsed = handleArguments(file, args, options); | |
const command = joinCommand(file, args); | |
const escapedCommand = getEscapedCommand(file, args); | |
logCommand(escapedCommand, parsed.options); | |
validateTimeout(parsed.options); | |
let spawned; | |
try { | |
spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options); | |
} catch (error) { | |
// Ensure the returned error is always both a promise and a child process | |
const dummySpawned = new childProcess.ChildProcess(); | |
const errorPromise = Promise.reject(makeError({ | |
error, | |
stdout: '', | |
stderr: '', | |
all: '', | |
command, | |
escapedCommand, | |
parsed, | |
timedOut: false, | |
isCanceled: false, | |
killed: false, | |
})); | |
mergePromise(dummySpawned, errorPromise); | |
return dummySpawned; | |
} | |
const spawnedPromise = getSpawnedPromise(spawned); | |
const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise); | |
const processDone = setExitHandler(spawned, parsed.options, timedPromise); | |
const context = {isCanceled: false}; | |
spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned)); | |
spawned.cancel = spawnedCancel.bind(null, spawned, context); | |
const handlePromise = async () => { | |
const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone); | |
const stdout = handleOutput(parsed.options, stdoutResult); | |
const stderr = handleOutput(parsed.options, stderrResult); | |
const all = handleOutput(parsed.options, allResult); | |
if (error || exitCode !== 0 || signal !== null) { | |
const returnedError = makeError({ | |
error, | |
exitCode, | |
signal, | |
stdout, | |
stderr, | |
all, | |
command, | |
escapedCommand, | |
parsed, | |
timedOut, | |
isCanceled: context.isCanceled || (parsed.options.signal ? parsed.options.signal.aborted : false), | |
killed: spawned.killed, | |
}); | |
if (!parsed.options.reject) { | |
return returnedError; | |
} | |
throw returnedError; | |
} | |
return { | |
command, | |
escapedCommand, | |
exitCode: 0, | |
stdout, | |
stderr, | |
all, | |
failed: false, | |
timedOut: false, | |
isCanceled: false, | |
killed: false, | |
}; | |
}; | |
const handlePromiseOnce = onetime(handlePromise); | |
handleInput(spawned, parsed.options); | |
spawned.all = makeAllStream(spawned, parsed.options); | |
addPipeMethods(spawned); | |
mergePromise(spawned, handlePromiseOnce); | |
return spawned; | |
} | |
export function execaSync(file, args, options) { | |
const parsed = handleArguments(file, args, options); | |
const command = joinCommand(file, args); | |
const escapedCommand = getEscapedCommand(file, args); | |
logCommand(escapedCommand, parsed.options); | |
const input = handleInputSync(parsed.options); | |
let result; | |
try { | |
result = childProcess.spawnSync(parsed.file, parsed.args, {...parsed.options, input}); | |
} catch (error) { | |
throw makeError({ | |
error, | |
stdout: '', | |
stderr: '', | |
all: '', | |
command, | |
escapedCommand, | |
parsed, | |
timedOut: false, | |
isCanceled: false, | |
killed: false, | |
}); | |
} | |
const stdout = handleOutput(parsed.options, result.stdout, result.error); | |
const stderr = handleOutput(parsed.options, result.stderr, result.error); | |
if (result.error || result.status !== 0 || result.signal !== null) { | |
const error = makeError({ | |
stdout, | |
stderr, | |
error: result.error, | |
signal: result.signal, | |
exitCode: result.status, | |
command, | |
escapedCommand, | |
parsed, | |
timedOut: result.error && result.error.code === 'ETIMEDOUT', | |
isCanceled: false, | |
killed: result.signal !== null, | |
}); | |
if (!parsed.options.reject) { | |
return error; | |
} | |
throw error; | |
} | |
return { | |
command, | |
escapedCommand, | |
exitCode: 0, | |
stdout, | |
stderr, | |
failed: false, | |
timedOut: false, | |
isCanceled: false, | |
killed: false, | |
}; | |
} | |
const normalizeScriptStdin = ({input, inputFile, stdio}) => input === undefined && inputFile === undefined && stdio === undefined | |
? {stdin: 'inherit'} | |
: {}; | |
const normalizeScriptOptions = (options = {}) => ({ | |
preferLocal: true, | |
...normalizeScriptStdin(options), | |
...options, | |
}); | |
function create$(options) { | |
function $(templatesOrOptions, ...expressions) { | |
if (!Array.isArray(templatesOrOptions)) { | |
return create$({...options, ...templatesOrOptions}); | |
} | |
const [file, ...args] = parseTemplates(templatesOrOptions, expressions); | |
return execa(file, args, normalizeScriptOptions(options)); | |
} | |
$.sync = (templates, ...expressions) => { | |
if (!Array.isArray(templates)) { | |
throw new TypeError('Please use $(options).sync`command` instead of $.sync(options)`command`.'); | |
} | |
const [file, ...args] = parseTemplates(templates, expressions); | |
return execaSync(file, args, normalizeScriptOptions(options)); | |
}; | |
return $; | |
} | |
export const $ = create$(); | |
export function execaCommand(command, options) { | |
const [file, ...args] = parseCommand(command); | |
return execa(file, args, options); | |
} | |
export function execaCommandSync(command, options) { | |
const [file, ...args] = parseCommand(command); | |
return execaSync(file, args, options); | |
} | |
export function execaNode(scriptPath, args, options = {}) { | |
if (args && !Array.isArray(args) && typeof args === 'object') { | |
options = args; | |
args = []; | |
} | |
const stdio = normalizeStdioNode(options); | |
const defaultExecArgv = process.execArgv.filter(arg => !arg.startsWith('--inspect')); | |
const { | |
nodePath = process.execPath, | |
nodeOptions = defaultExecArgv, | |
} = options; | |
return execa( | |
nodePath, | |
[ | |
...nodeOptions, | |
scriptPath, | |
...(Array.isArray(args) ? args : []), | |
], | |
{ | |
...options, | |
stdin: undefined, | |
stdout: undefined, | |
stderr: undefined, | |
stdio, | |
shell: false, | |
}, | |
); | |
} |