Permalink
Cannot retrieve contributors at this time
120 lines (94 sloc)
3 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/lib/command.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 {ChildProcess} from 'node:child_process'; | |
const normalizeArgs = (file, args = []) => { | |
if (!Array.isArray(args)) { | |
return [file]; | |
} | |
return [file, ...args]; | |
}; | |
const NO_ESCAPE_REGEXP = /^[\w.-]+$/; | |
const DOUBLE_QUOTES_REGEXP = /"/g; | |
const escapeArg = arg => { | |
if (typeof arg !== 'string' || NO_ESCAPE_REGEXP.test(arg)) { | |
return arg; | |
} | |
return `"${arg.replace(DOUBLE_QUOTES_REGEXP, '\\"')}"`; | |
}; | |
export const joinCommand = (file, args) => normalizeArgs(file, args).join(' '); | |
export const getEscapedCommand = (file, args) => normalizeArgs(file, args).map(arg => escapeArg(arg)).join(' '); | |
const SPACES_REGEXP = / +/g; | |
// Handle `execaCommand()` | |
export const parseCommand = command => { | |
const tokens = []; | |
for (const token of command.trim().split(SPACES_REGEXP)) { | |
// Allow spaces to be escaped by a backslash if not meant as a delimiter | |
const previousToken = tokens[tokens.length - 1]; | |
if (previousToken && previousToken.endsWith('\\')) { | |
// Merge previous token with current one | |
tokens[tokens.length - 1] = `${previousToken.slice(0, -1)} ${token}`; | |
} else { | |
tokens.push(token); | |
} | |
} | |
return tokens; | |
}; | |
const parseExpression = expression => { | |
const typeOfExpression = typeof expression; | |
if (typeOfExpression === 'string') { | |
return expression; | |
} | |
if (typeOfExpression === 'number') { | |
return String(expression); | |
} | |
if ( | |
typeOfExpression === 'object' | |
&& expression !== null | |
&& !(expression instanceof ChildProcess) | |
&& 'stdout' in expression | |
) { | |
const typeOfStdout = typeof expression.stdout; | |
if (typeOfStdout === 'string') { | |
return expression.stdout; | |
} | |
if (Buffer.isBuffer(expression.stdout)) { | |
return expression.stdout.toString(); | |
} | |
throw new TypeError(`Unexpected "${typeOfStdout}" stdout in template expression`); | |
} | |
throw new TypeError(`Unexpected "${typeOfExpression}" in template expression`); | |
}; | |
const concatTokens = (tokens, nextTokens, isNew) => isNew || tokens.length === 0 || nextTokens.length === 0 | |
? [...tokens, ...nextTokens] | |
: [ | |
...tokens.slice(0, -1), | |
`${tokens[tokens.length - 1]}${nextTokens[0]}`, | |
...nextTokens.slice(1), | |
]; | |
const parseTemplate = ({templates, expressions, tokens, index, template}) => { | |
const templateString = template ?? templates.raw[index]; | |
const templateTokens = templateString.split(SPACES_REGEXP).filter(Boolean); | |
const newTokens = concatTokens( | |
tokens, | |
templateTokens, | |
templateString.startsWith(' '), | |
); | |
if (index === expressions.length) { | |
return newTokens; | |
} | |
const expression = expressions[index]; | |
const expressionTokens = Array.isArray(expression) | |
? expression.map(expression => parseExpression(expression)) | |
: [parseExpression(expression)]; | |
return concatTokens( | |
newTokens, | |
expressionTokens, | |
templateString.endsWith(' '), | |
); | |
}; | |
export const parseTemplates = (templates, expressions) => { | |
let tokens = []; | |
for (const [index, template] of templates.entries()) { | |
tokens = parseTemplate({templates, expressions, tokens, index, template}); | |
} | |
return tokens; | |
}; |