mirror of
				https://github.com/actions/setup-dotnet.git
				synced 2025-11-04 04:03:45 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			126 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
const path = require('path');
 | 
						|
const niceTry = require('nice-try');
 | 
						|
const resolveCommand = require('./util/resolveCommand');
 | 
						|
const escape = require('./util/escape');
 | 
						|
const readShebang = require('./util/readShebang');
 | 
						|
const semver = require('semver');
 | 
						|
 | 
						|
const isWin = process.platform === 'win32';
 | 
						|
const isExecutableRegExp = /\.(?:com|exe)$/i;
 | 
						|
const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
 | 
						|
 | 
						|
// `options.shell` is supported in Node ^4.8.0, ^5.7.0 and >= 6.0.0
 | 
						|
const supportsShellOption = niceTry(() => semver.satisfies(process.version, '^4.8.0 || ^5.7.0 || >= 6.0.0', true)) || false;
 | 
						|
 | 
						|
function detectShebang(parsed) {
 | 
						|
    parsed.file = resolveCommand(parsed);
 | 
						|
 | 
						|
    const shebang = parsed.file && readShebang(parsed.file);
 | 
						|
 | 
						|
    if (shebang) {
 | 
						|
        parsed.args.unshift(parsed.file);
 | 
						|
        parsed.command = shebang;
 | 
						|
 | 
						|
        return resolveCommand(parsed);
 | 
						|
    }
 | 
						|
 | 
						|
    return parsed.file;
 | 
						|
}
 | 
						|
 | 
						|
function parseNonShell(parsed) {
 | 
						|
    if (!isWin) {
 | 
						|
        return parsed;
 | 
						|
    }
 | 
						|
 | 
						|
    // Detect & add support for shebangs
 | 
						|
    const commandFile = detectShebang(parsed);
 | 
						|
 | 
						|
    // We don't need a shell if the command filename is an executable
 | 
						|
    const needsShell = !isExecutableRegExp.test(commandFile);
 | 
						|
 | 
						|
    // If a shell is required, use cmd.exe and take care of escaping everything correctly
 | 
						|
    // Note that `forceShell` is an hidden option used only in tests
 | 
						|
    if (parsed.options.forceShell || needsShell) {
 | 
						|
        // Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/`
 | 
						|
        // The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument
 | 
						|
        // Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called,
 | 
						|
        // we need to double escape them
 | 
						|
        const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
 | 
						|
 | 
						|
        // Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar)
 | 
						|
        // This is necessary otherwise it will always fail with ENOENT in those cases
 | 
						|
        parsed.command = path.normalize(parsed.command);
 | 
						|
 | 
						|
        // Escape command & arguments
 | 
						|
        parsed.command = escape.command(parsed.command);
 | 
						|
        parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
 | 
						|
 | 
						|
        const shellCommand = [parsed.command].concat(parsed.args).join(' ');
 | 
						|
 | 
						|
        parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`];
 | 
						|
        parsed.command = process.env.comspec || 'cmd.exe';
 | 
						|
        parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
 | 
						|
    }
 | 
						|
 | 
						|
    return parsed;
 | 
						|
}
 | 
						|
 | 
						|
function parseShell(parsed) {
 | 
						|
    // If node supports the shell option, there's no need to mimic its behavior
 | 
						|
    if (supportsShellOption) {
 | 
						|
        return parsed;
 | 
						|
    }
 | 
						|
 | 
						|
    // Mimic node shell option
 | 
						|
    // See https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335
 | 
						|
    const shellCommand = [parsed.command].concat(parsed.args).join(' ');
 | 
						|
 | 
						|
    if (isWin) {
 | 
						|
        parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe';
 | 
						|
        parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`];
 | 
						|
        parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
 | 
						|
    } else {
 | 
						|
        if (typeof parsed.options.shell === 'string') {
 | 
						|
            parsed.command = parsed.options.shell;
 | 
						|
        } else if (process.platform === 'android') {
 | 
						|
            parsed.command = '/system/bin/sh';
 | 
						|
        } else {
 | 
						|
            parsed.command = '/bin/sh';
 | 
						|
        }
 | 
						|
 | 
						|
        parsed.args = ['-c', shellCommand];
 | 
						|
    }
 | 
						|
 | 
						|
    return parsed;
 | 
						|
}
 | 
						|
 | 
						|
function parse(command, args, options) {
 | 
						|
    // Normalize arguments, similar to nodejs
 | 
						|
    if (args && !Array.isArray(args)) {
 | 
						|
        options = args;
 | 
						|
        args = null;
 | 
						|
    }
 | 
						|
 | 
						|
    args = args ? args.slice(0) : []; // Clone array to avoid changing the original
 | 
						|
    options = Object.assign({}, options); // Clone object to avoid changing the original
 | 
						|
 | 
						|
    // Build our parsed object
 | 
						|
    const parsed = {
 | 
						|
        command,
 | 
						|
        args,
 | 
						|
        options,
 | 
						|
        file: undefined,
 | 
						|
        original: {
 | 
						|
            command,
 | 
						|
            args,
 | 
						|
        },
 | 
						|
    };
 | 
						|
 | 
						|
    // Delegate further parsing to shell or non-shell
 | 
						|
    return options.shell ? parseShell(parsed) : parseNonShell(parsed);
 | 
						|
}
 | 
						|
 | 
						|
module.exports = parse;
 |