"use strict" ; import * as fs from "fs" ; import * as path from "path" ; import * as cp from "child_process" ; import * as vscode from "vscode" ; import { randomBytes , createHash , BinaryLike } from "crypto" ; import { Target } from "./meson/types" ; import { ExtensionConfiguration } from "./types" ; import { getMesonBuildOptions } from "./meson/introspection" ; export async function exec ( command , args , options = { } ) { return new Promise < { stdout : string ; stderr : string ; error ? : cp . ExecException ; } > ( ( resolve , reject ) => { cp . execFile ( command , args , options , ( error , stdout , stderr ) => { if ( error ) { reject ( { error , stdout , stderr } ) ; } else { resolve ( { stdout , stderr } ) ; } } ) ; } ) ; } export function execStream ( command , args , options ) { const spawned = cp . spawn ( command , args , options ) ; return { onLine ( fn ) { spawned . stdout . on ( "data" , ( msg ) => fn ( msg . toString ( ) , false ) ) ; spawned . stderr . on ( "data" , ( msg ) => fn ( msg . toString ( ) , true ) ) ; } , kill ( signal ? ) { spawned . kill ( signal || "SIGKILL" ) ; } , finishP ( ) { return new Promise < number > ( res => { spawned . on ( "exit" , code => res ( code ) ) ; } ) ; } } ; } export function execAsTask ( command , args , options , revealMode = vscode . TaskRevealKind . Silent ) { const task = new vscode . Task ( { type : "temp" } , command , "Meson" , new vscode . ProcessExecution ( command , args , options ) ) ; task . presentationOptions . echo = false ; task . presentationOptions . focus = false ; task . presentationOptions . reveal = revealMode ; return vscode . tasks . executeTask ( task ) ; } export async function parseJSONFileIfExists < T = object > ( path ) { try { const data = await fs . promises . readFile ( path ) ; return JSON . parse ( data . toString ( ) ) as T ; } catch ( err ) { return false ; } } let _channel ; export function getOutputChannel ( ) { if ( ! _channel ) { _channel = vscode . window . createOutputChannel ( "Meson Build" ) ; } return _channel ; } export function thisExtension ( ) { const ext = vscode . extensions . getExtension ( "mesonbuild.meson" ) ; if ( ext ) return ext ; else throw new Error ( "Extension not found" ) ; } export function extensionRelative ( filepath ) { return path . join ( thisExtension ( ) . extensionPath , filepath ) ; } export function workspaceRelative ( filepath ) { return path . join ( vscode . workspace . rootPath , filepath ) ; } export async function getTargetName ( target ) { const buildDir = workspaceRelative ( extensionConfiguration ( "buildFolder" ) ) ; const buildOptions = await getMesonBuildOptions ( buildDir ) ; const layoutOption = buildOptions . filter ( o => o . name === "layout" ) [ 0 ] ; if ( layoutOption . value === "mirror" ) { const relativePath = path . relative ( vscode . workspace . rootPath , path . dirname ( target . defined_in ) ) ; return path . posix . join ( relativePath , target . name ) ; } else { return `meson-out/${ target . name }` ; } } export function randomString ( length = 4 ) { return randomBytes ( length ) . toString ( "base64" ) . substr ( 0 , length ) ; } export function hash ( input ) { const hashObj = createHash ( "sha1" ) ; hashObj . update ( input ) ; return hashObj . digest ( "hex" ) ; } export function getConfiguration ( ) { return vscode . workspace . getConfiguration ( "mesonbuild" ) ; } export function extensionConfiguration < K extends keyof ExtensionConfiguration > ( key ) { return getConfiguration ( ) . get < ExtensionConfiguration [ K ] > ( key ) ; } export function extensionConfigurationSet < K extends keyof ExtensionConfiguration > ( key , value , target = vscode . ConfigurationTarget . Global ) { return getConfiguration ( ) . update ( key , value , target ) ; } export function arrayIncludes < T > ( array , value ) { return array . indexOf ( value ) !== - 1 ; } export function isThenable < T > ( x ) { return arrayIncludes ( Object . getOwnPropertyNames ( x ) , "then" ) ; }