11import fs = require( "fs" ) ;
22import path = require( "path" ) ;
3+ import { R_OK } from "constants" ;
34import * as url from "url" ;
4- import { execSync } from "child_process" ;
5+ import { exec } from "child_process" ;
56import * as vscode from "vscode" ;
67import { config , schemas , workspaceState , terminals } from "../extension" ;
78
@@ -222,7 +223,7 @@ export function notNull(el: any): boolean {
222223 return el !== null ;
223224}
224225
225- export function portFromDockerCompose ( ) : { port : number ; docker : boolean } {
226+ export async function portFromDockerCompose ( ) : Promise < { port : number ; docker : boolean } > {
226227 const { "docker-compose" : dockerCompose = { } } = config ( "conn" ) ;
227228 const { service, file = "docker-compose.yml" , internalPort = 52773 , envFile } = dockerCompose ;
228229 if ( ! internalPort || ! file || ! service || service === "" ) {
@@ -232,36 +233,50 @@ export function portFromDockerCompose(): { port: number; docker: boolean } {
232233 const workspaceFolderPath = workspaceFolderUri ( ) . fsPath ;
233234 const workspaceRootPath = vscode . workspace . workspaceFolders [ 0 ] . uri . fsPath ;
234235
235- const cwd = fs . existsSync ( path . join ( workspaceFolderPath , file ) )
236- ? workspaceFolderPath
237- : fs . existsSync ( path . join ( workspaceRootPath , file ) )
238- ? workspaceRootPath
239- : null ;
236+ const cwd : string = await new Promise ( ( resolve , reject ) => {
237+ fs . access ( path . join ( workspaceFolderPath , file ) , R_OK , ( error ) => {
238+ if ( error ) {
239+ fs . access ( path . join ( workspaceRootPath , file ) , R_OK , ( error ) => {
240+ if ( error ) {
241+ reject ( new Error ( `File '${ file } ' not found.` ) ) ;
242+ } else {
243+ resolve ( workspaceRootPath ) ;
244+ }
245+ } ) ;
246+ } else {
247+ resolve ( workspaceFolderPath ) ;
248+ }
249+ } ) ;
250+ } ) ;
240251
241252 if ( ! cwd ) {
242253 return result ;
243254 }
244255
245256 const envFileParam = envFile ? `--env-file ${ envFile } ` : "" ;
246- const cmd = `docker-compose -f ${ file } ${ envFileParam } port --protocol=tcp ${ service } ${ internalPort } ` ;
257+ const cmd = `docker-compose -f ${ file } ${ envFileParam } ` ;
247258
248- try {
249- const serviceLine = execSync ( cmd , {
250- cwd,
251- } )
252- . toString ( )
253- . replace ( "/r" , "" )
254- . split ( "/n" )
255- . pop ( ) ;
256- const servicePortMatch = serviceLine . match ( new RegExp ( `:(\\d+)` ) ) ;
257- if ( servicePortMatch ) {
258- const [ , newPort ] = servicePortMatch ;
259- return { port : parseInt ( newPort , 10 ) , docker : true } ;
260- }
261- } catch ( e ) {
262- // nope
263- }
264- return result ;
259+ return new Promise ( ( resolve , reject ) => {
260+ exec ( `${ cmd } ps --services --filter 'status=running'` , { cwd } , ( error , stdout ) => {
261+ if ( error ) {
262+ reject ( error . message ) ;
263+ }
264+ if ( ! stdout . replace ( "\r" , "" ) . split ( "\n" ) . includes ( service ) ) {
265+ reject ( `Service '${ service } ' not found in '${ file } ', or not running.` ) ;
266+ }
267+
268+ exec ( `${ cmd } port --protocol=tcp ${ service } ${ internalPort } ` , { cwd } , ( error , stdout ) => {
269+ if ( error ) {
270+ reject ( error . message ) ;
271+ }
272+ const [ , port ] = stdout . match ( / : ( \d + ) / ) || [ ] ;
273+ if ( ! port ) {
274+ reject ( `Port ${ internalPort } not published for service '${ service } '.` ) ;
275+ }
276+ resolve ( { port : parseInt ( port , 10 ) , docker : true } ) ;
277+ } ) ;
278+ } ) ;
279+ } ) ;
265280}
266281
267282export async function terminalWithDocker ( ) : Promise < vscode . Terminal > {
0 commit comments