123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- 'use strict';
- var exec = require('child_process').exec;
- var execSync = require('child_process').execSync;
- var fs = require('fs');
- var path = require('path');
- var access = fs.access;
- var accessSync = fs.accessSync;
- var constants = fs.constants || fs;
- var isUsingWindows = process.platform == 'win32'
- var fileNotExists = function(commandName, callback){
- access(commandName, constants.F_OK,
- function(err){
- callback(!err);
- });
- };
- var fileNotExistsSync = function(commandName){
- try{
- accessSync(commandName, constants.F_OK);
- return false;
- }catch(e){
- return true;
- }
- };
- var localExecutable = function(commandName, callback){
- access(commandName, constants.F_OK | constants.X_OK,
- function(err){
- callback(null, !err);
- });
- };
- var localExecutableSync = function(commandName){
- try{
- accessSync(commandName, constants.F_OK | constants.X_OK);
- return true;
- }catch(e){
- return false;
- }
- }
- var commandExistsUnix = function(commandName, cleanedCommandName, callback) {
- fileNotExists(commandName, function(isFile){
- if(!isFile){
- var child = exec('command -v ' + cleanedCommandName +
- ' 2>/dev/null' +
- ' && { echo >&1 ' + cleanedCommandName + '; exit 0; }',
- function (error, stdout, stderr) {
- callback(null, !!stdout);
- });
- return;
- }
- localExecutable(commandName, callback);
- });
- }
- var commandExistsWindows = function(commandName, cleanedCommandName, callback) {
- // Regex from Julio from: https://stackoverflow.com/questions/51494579/regex-windows-path-validator
- if (!(/^(?!(?:.*\s|.*\.|\W+)$)(?:[a-zA-Z]:)?(?:(?:[^<>:"\|\?\*\n])+(?:\/\/|\/|\\\\|\\)?)+$/m.test(commandName))) {
- callback(null, false);
- return;
- }
- var child = exec('where ' + cleanedCommandName,
- function (error) {
- if (error !== null){
- callback(null, false);
- } else {
- callback(null, true);
- }
- }
- )
- }
- var commandExistsUnixSync = function(commandName, cleanedCommandName) {
- if(fileNotExistsSync(commandName)){
- try {
- var stdout = execSync('command -v ' + cleanedCommandName +
- ' 2>/dev/null' +
- ' && { echo >&1 ' + cleanedCommandName + '; exit 0; }'
- );
- return !!stdout;
- } catch (error) {
- return false;
- }
- }
- return localExecutableSync(commandName);
- }
- var commandExistsWindowsSync = function(commandName, cleanedCommandName, callback) {
- // Regex from Julio from: https://stackoverflow.com/questions/51494579/regex-windows-path-validator
- if (!(/^(?!(?:.*\s|.*\.|\W+)$)(?:[a-zA-Z]:)?(?:(?:[^<>:"\|\?\*\n])+(?:\/\/|\/|\\\\|\\)?)+$/m.test(commandName))) {
- return false;
- }
- try {
- var stdout = execSync('where ' + cleanedCommandName, {stdio: []});
- return !!stdout;
- } catch (error) {
- return false;
- }
- }
- var cleanInput = function(s) {
- if (/[^A-Za-z0-9_\/:=-]/.test(s)) {
- s = "'"+s.replace(/'/g,"'\\''")+"'";
- s = s.replace(/^(?:'')+/g, '') // unduplicate single-quote at the beginning
- .replace(/\\'''/g, "\\'" ); // remove non-escaped single-quote if there are enclosed between 2 escaped
- }
- return s;
- }
- if (isUsingWindows) {
- cleanInput = function(s) {
- var isPathName = /[\\]/.test(s);
- if (isPathName) {
- var dirname = '"' + path.dirname(s) + '"';
- var basename = '"' + path.basename(s) + '"';
- return dirname + ':' + basename;
- }
- return '"' + s + '"';
- }
- }
- module.exports = function commandExists(commandName, callback) {
- var cleanedCommandName = cleanInput(commandName);
- if (!callback && typeof Promise !== 'undefined') {
- return new Promise(function(resolve, reject){
- commandExists(commandName, function(error, output) {
- if (output) {
- resolve(commandName);
- } else {
- reject(error);
- }
- });
- });
- }
- if (isUsingWindows) {
- commandExistsWindows(commandName, cleanedCommandName, callback);
- } else {
- commandExistsUnix(commandName, cleanedCommandName, callback);
- }
- };
- module.exports.sync = function(commandName) {
- var cleanedCommandName = cleanInput(commandName);
- if (isUsingWindows) {
- return commandExistsWindowsSync(commandName, cleanedCommandName);
- } else {
- return commandExistsUnixSync(commandName, cleanedCommandName);
- }
- };
|