<commit_before>import chalk from 'chalk'
import childProcess from 'child_process'
import template from 'lodash.template'
import fs from 'fs'
import path from 'path'
import readline from 'readline'
import { RunJSError } from './common'

export const logger = {
  debug: (...args) => {
    console.log(chalk.blue(...args))
  },
  info: (...args) => {
    console.log(chalk.bold(...args))
  },
  log: (...args) => {
    console.log(...args)
  },
  warning: (...args) => {
    console.warn(chalk.yellow(...args))
  },
  error: (...args) => {
    console.error(chalk.red(...args))
  }
}

const loggerAlias = logger

function runSync (command, options) {
  // Prepare options for execSync command (don't need async and stdio should have default value)
  const execOptions = Object.assign({}, options)
  delete execOptions.async
  if (execOptions.stdio === 'inherit') {
    delete execOptions.stdio
  }

  try {
    const execSyncBuffer = childProcess.execSync(command, execOptions)
    if (options.stdio === 'inherit') {
      // execSync do handle stdio option, but when stdio=inherit, execSync returns null. We can fix that
      // by not passing stdio=inherit and writing outcome separately. Thanks to this stdout will be streamed and sync
      // run function will still return child process outcome.
      process.stdout.write(execSyncBuffer)
      // stderr is inherited by default
    }
    return execSyncBuffer.toString()
  } catch (error) {
    throw new RunJSError(error.message)
  }
}

function runAsync (command, options) {
  return new Promise((resolve, reject) => {
    const spawnOptions = Object.assign({shell: true}, options)
    const timeout = spawnOptions.timeout
    delete spawnOptions.async

    return new Promise((resolve, reject) => {
      const asyncProcess = childProcess.spawn(command, spawnOptions)
      asyncProcess.on('error', (error) => {
        reject(new Error(`Failed to start command: ${command}; ${error}`))
      })

      asyncProcess.on('close', (exitCode) => {
        if (exitCode === 0) {
          resolve(exitCode)
        } else {
          reject(new Error(`Command failed: ${command} with exit code ${exitCode}`))
        }
      })

      if (timeout) {
        setTimeout(() => {
          asyncProcess.kill()
          reject(new Error(`Command timeout: ${command}`))
        }, timeout)
      }
    })
  })
}

export function run (command, options = {}, logger = loggerAlias) {
  const binPath = path.resolve('./node_modules/.bin')<commit_msg>runAsync: remove second new Promise<commit_after>import chalk from 'chalk'
import childProcess from 'child_process'
import template from 'lodash.template'
import fs from 'fs'
import path from 'path'
import readline from 'readline'
import { RunJSError } from './common'

export const logger = {
  debug: (...args) => {
    console.log(chalk.blue(...args))
  },
  info: (...args) => {
    console.log(chalk.bold(...args))
  },
  log: (...args) => {
    console.log(...args)
  },
  warning: (...args) => {
    console.warn(chalk.yellow(...args))
  },
  error: (...args) => {
    console.error(chalk.red(...args))
  }
}

const loggerAlias = logger

function runSync (command, options) {
  // Prepare options for execSync command (don't need async and stdio should have default value)
  const execOptions = Object.assign({}, options)
  delete execOptions.async
  if (execOptions.stdio === 'inherit') {
    delete execOptions.stdio
  }

  try {
    const execSyncBuffer = childProcess.execSync(command, execOptions)
    if (options.stdio === 'inherit') {
      // execSync do handle stdio option, but when stdio=inherit, execSync returns null. We can fix that
      // by not passing stdio=inherit and writing outcome separately. Thanks to this stdout will be streamed and sync
      // run function will still return child process outcome.
      process.stdout.write(execSyncBuffer)
      // stderr is inherited by default
    }
    return execSyncBuffer.toString()
  } catch (error) {
    throw new RunJSError(error.message)
  }
}

function runAsync (command, options) {
  const spawnOptions = Object.assign({shell: true}, options)
  const timeout = spawnOptions.timeout
  delete spawnOptions.async

  return new Promise((resolve, reject) => {
    const asyncProcess = childProcess.spawn(command, spawnOptions)
    asyncProcess.on('error', (error) => {
      reject(new Error(`Failed to start command: ${command}; ${error}`))
    })

    asyncProcess.on('close', (exitCode) => {
      if (exitCode === 0) {
        resolve(exitCode)
      } else {
        reject(new Error(`Command failed: ${command} with exit code ${exitCode}`))
      }
    })

    if (timeout) {
      setTimeout(() => {
        asyncProcess.kill()
        reject(new Error(`Command timeout: ${command}`))
      }, timeout)
    }
  })
}

export function run (command, options = {}, logger = loggerAlias) {
  const binPath = path.resolve('./node_modules/.bin')
{'fraction_non_alphanumeric': 0.1377768746189799, 'fraction_numerical': 0.000406421459053038, 'mean_word_length': 3.061056105610561, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '50867', 'n_tokens_mistral': 1456, 'n_tokens_neox': 1435, 'n_words': 415}