11// Copyright (c) Microsoft Corporation. All rights reserved. 
22// Licensed under the MIT License. 
3- import  {  spawn  }  from  'child_process' ; 
3+ import  {  exec ,   spawn  }  from  'child_process' ; 
44import  {  Observable  }  from  'rxjs/Observable' ; 
55import  *  as  tk  from  'tree-kill' ; 
66import  {  Disposable  }  from  'vscode' ; 
@@ -14,6 +14,7 @@ import {
1414 IProcessService , 
1515 ObservableExecutionResult , 
1616 Output , 
17+  ShellOptions , 
1718 SpawnOptions , 
1819 StdErrError 
1920}  from  './types' ; 
@@ -37,23 +38,11 @@ export class ProcessService implements IProcessService {
3738 }  catch  { 
3839 // Ignore. 
3940 } 
40- 
4141 } 
42-  public  execObservable ( file : string ,  args : string [ ] ,  options : SpawnOptions  =  { } ) : ObservableExecutionResult < string >  { 
43-  const  encoding  =  options . encoding  =  typeof  options . encoding  ===  'string'  &&  options . encoding . length  >  0  ? options . encoding  : DEFAULT_ENCODING ; 
44-  delete  options . encoding ; 
45-  const  spawnOptions  =  {  ...options  } ; 
46-  if  ( ! spawnOptions . env  ||  Object . keys ( spawnOptions ) . length  ===  0 )  { 
47-  const  env  =  this . env  ? this . env  : process . env ; 
48-  spawnOptions . env  =  {  ...env  } ; 
49-  } 
50- 
51-  // Always ensure we have unbuffered output. 
52-  spawnOptions . env . PYTHONUNBUFFERED  =  '1' ; 
53-  if  ( ! spawnOptions . env . PYTHONIOENCODING )  { 
54-  spawnOptions . env . PYTHONIOENCODING  =  'utf-8' ; 
55-  } 
5642
43+  public  execObservable ( file : string ,  args : string [ ] ,  options : SpawnOptions  =  { } ) : ObservableExecutionResult < string >  { 
44+  const  spawnOptions  =  this . getDefaultOptions ( options ) ; 
45+  const  encoding  =  spawnOptions . encoding  ? spawnOptions . encoding  : 'utf8' ; 
5746 const  proc  =  spawn ( file ,  args ,  spawnOptions ) ; 
5847 let  procExited  =  false ; 
5948
@@ -109,19 +98,8 @@ export class ProcessService implements IProcessService {
10998 } ; 
11099 } 
111100 public  exec ( file : string ,  args : string [ ] ,  options : SpawnOptions  =  { } ) : Promise < ExecutionResult < string > >  { 
112-  const  encoding  =  options . encoding  =  typeof  options . encoding  ===  'string'  &&  options . encoding . length  >  0  ? options . encoding  : DEFAULT_ENCODING ; 
113-  delete  options . encoding ; 
114-  const  spawnOptions  =  {  ...options  } ; 
115-  if  ( ! spawnOptions . env  ||  Object . keys ( spawnOptions ) . length  ===  0 )  { 
116-  const  env  =  this . env  ? this . env  : process . env ; 
117-  spawnOptions . env  =  {  ...env  } ; 
118-  } 
119- 
120-  // Always ensure we have unbuffered output. 
121-  spawnOptions . env . PYTHONUNBUFFERED  =  '1' ; 
122-  if  ( ! spawnOptions . env . PYTHONIOENCODING )  { 
123-  spawnOptions . env . PYTHONIOENCODING  =  'utf-8' ; 
124-  } 
101+  const  spawnOptions  =  this . getDefaultOptions ( options ) ; 
102+  const  encoding  =  spawnOptions . encoding  ? spawnOptions . encoding  : 'utf8' ; 
125103 const  proc  =  spawn ( file ,  args ,  spawnOptions ) ; 
126104 const  deferred  =  createDeferred < ExecutionResult < string > > ( ) ; 
127105 const  disposables : Disposable [ ]  =  [ ] ; 
@@ -171,4 +149,45 @@ export class ProcessService implements IProcessService {
171149
172150 return  deferred . promise ; 
173151 } 
152+ 
153+  public  shellExec ( command : string ,  options : ShellOptions  =  { } ) : Promise < ExecutionResult < string > >  { 
154+  const  shellOptions  =  this . getDefaultOptions ( options ) ; 
155+  return  new  Promise ( ( resolve ,  reject )  =>  { 
156+  exec ( command ,  shellOptions ,  ( e ,  stdout ,  stderr )  =>  { 
157+  if  ( e  &&  e  !==  null )  { 
158+  reject ( e ) ; 
159+  }  else  if  ( shellOptions . throwOnStdErr  &&  stderr  &&  stderr . length )  { 
160+  reject ( new  Error ( stderr ) ) ; 
161+  }  else  { 
162+  // Make sure stderr is undefined if we actually had none. This is checked 
163+  // elsewhere because that's how exec behaves. 
164+  resolve ( {  stderr : stderr  &&  stderr . length  >  0  ? stderr  : undefined ,  stdout : stdout  } ) ; 
165+  } 
166+  } ) ; 
167+  } ) ; 
168+  } 
169+ 
170+  private  getDefaultOptions < T  extends  ( ShellOptions  |  SpawnOptions ) > ( options : T )  : T  { 
171+  const  execOptions  =  options  as  SpawnOptions ; 
172+  const  defaultOptions  =  JSON . parse ( JSON . stringify ( options ) ) ; 
173+  if  ( execOptions ) 
174+  { 
175+  const  encoding  =  execOptions . encoding  =  typeof  execOptions . encoding  ===  'string'  &&  execOptions . encoding . length  >  0  ? execOptions . encoding  : DEFAULT_ENCODING ; 
176+  delete  execOptions . encoding ; 
177+  defaultOptions . encoding  =  encoding ; 
178+  } 
179+  if  ( ! defaultOptions . env  ||  Object . keys ( defaultOptions ) . length  ===  0 )  { 
180+  const  env  =  this . env  ? this . env  : process . env ; 
181+  defaultOptions . env  =  {  ...env  } ; 
182+  } 
183+ 
184+  // Always ensure we have unbuffered output. 
185+  defaultOptions . env . PYTHONUNBUFFERED  =  '1' ; 
186+  if  ( ! defaultOptions . env . PYTHONIOENCODING )  { 
187+  defaultOptions . env . PYTHONIOENCODING  =  'utf-8' ; 
188+  } 
189+ 
190+  return  defaultOptions ; 
191+  } 
192+ 
174193} 
0 commit comments