import * as cp from 'child_process' ; import * as os from 'os' ; import * as vscode from 'vscode' ; import { isWindows } from '../constants' ; import { localize } from '../localize' ; export namespace cpUtils { export async function executeCommand ( outputChannel , workingDirectory , command , ... args ) { const result = await tryExecuteCommand ( outputChannel , workingDirectory , command , ... args ) ; if ( result . code !== 0 ) { if ( outputChannel ) { outputChannel . show ( ) ; throw new Error ( localize ( 'commandErrorWithOutput' , 'Failed to run "{0}" command. Check output window for more details.' , command ) ) ; } else { throw new Error ( localize ( 'commandError' , 'Command "{0} {1}" failed with exit code "{2}":{3}{4}' , command , result . formattedArgs , result . code , os . EOL , result . cmdOutputIncludingStderr ) ) ; } } else { if ( outputChannel ) { outputChannel . appendLine ( localize ( 'finishedRunningCommand' , 'Finished running command: "{0} {1}".' , command , result . formattedArgs ) ) ; } } return result . cmdOutput ; } export async function tryExecuteCommand ( outputChannel , workingDirectory , command , ... args ) { return await new Promise ( ( resolve , reject ) : void => { let cmdOutput = '' ; let cmdOutputIncludingStderr = '' ; const formattedArgs = args . join ( ' ' ) ; workingDirectory = workingDirectory || os . tmpdir ( ) ; const options = { cwd : workingDirectory , shell : true } ; const childProc = cp . spawn ( command , args , options ) ; if ( outputChannel ) { outputChannel . appendLine ( localize ( 'runningCommand' , 'Running command: "{0} {1}"...' , command , formattedArgs ) ) ; } childProc . stdout . on ( 'data' , ( data ) => { data = data . toString ( ) ; cmdOutput = cmdOutput . concat ( data ) ; cmdOutputIncludingStderr = cmdOutputIncludingStderr . concat ( data ) ; if ( outputChannel ) { outputChannel . append ( data ) ; } } ) ; childProc . stderr . on ( 'data' , ( data ) => { data = data . toString ( ) ; cmdOutputIncludingStderr = cmdOutputIncludingStderr . concat ( data ) ; if ( outputChannel ) { outputChannel . append ( data ) ; } } ) ; childProc . on ( 'error' , reject ) ; childProc . on ( 'close' , ( code ) => { resolve ( { code , cmdOutput , cmdOutputIncludingStderr , formattedArgs } ) ; } ) ; } ) ; } export interface ICommandResult { code : number ; cmdOutput : string ; cmdOutputIncludingStderr : string ; formattedArgs : string ; } const quotationMark = isWindows ? '"' : '\'' ; /**
     * Ensures spaces and special characters (most notably $) are preserved
     */ export function wrapArgInQuotes ( arg ) { return quotationMark + arg + quotationMark ; } }