• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2
3const fs = require('graceful-fs')
4const childProcess = require('child_process')
5
6function startsWith (str, search, pos) {
7  if (String.prototype.startsWith) {
8    return str.startsWith(search, pos)
9  }
10
11  return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search
12}
13
14function processExecSync (file, args, options) {
15  var child, error, timeout, tmpdir, command
16  command = makeCommand(file, args)
17
18  /*
19    this function emulates child_process.execSync for legacy node <= 0.10.x
20    derived from https://github.com/gvarsanyi/sync-exec/blob/master/js/sync-exec.js
21  */
22
23  options = options || {}
24  // init timeout
25  timeout = Date.now() + options.timeout
26  // init tmpdir
27  var osTempBase = '/tmp'
28  var os = determineOS()
29  osTempBase = '/tmp'
30
31  if (process.env.TMP) {
32    osTempBase = process.env.TMP
33  }
34
35  if (osTempBase[osTempBase.length - 1] !== '/') {
36    osTempBase += '/'
37  }
38
39  tmpdir = osTempBase + 'processExecSync.' + Date.now() + Math.random()
40  fs.mkdirSync(tmpdir)
41
42  // init command
43  if (os === 'linux') {
44    command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir +
45      '/stderr); echo $? > ' + tmpdir + '/status'
46  } else {
47    command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir +
48      '/stderr) | echo %errorlevel% > ' + tmpdir + '/status | exit'
49  }
50
51  // init child
52  child = childProcess.exec(command, options)
53
54  var maxTry = 100000 // increases the test time by 6 seconds on win-2016-node-0.10
55  var tryCount = 0
56  while (tryCount < maxTry) {
57    try {
58      var x = fs.readFileSync(tmpdir + '/status')
59      if (x.toString() === '0') {
60        break
61      }
62    } catch (ignore) {}
63    tryCount++
64    if (Date.now() > timeout) {
65      error = child
66      break
67    }
68  }
69
70  ['stdout', 'stderr', 'status'].forEach(function (file) {
71    child[file] = fs.readFileSync(tmpdir + '/' + file, options.encoding)
72    setTimeout(unlinkFile, 500, tmpdir + '/' + file)
73  })
74
75  child.status = Number(child.status)
76  if (child.status !== 0) {
77    error = child
78  }
79
80  try {
81    fs.rmdirSync(tmpdir)
82  } catch (ignore) {}
83  if (error) {
84    throw error
85  }
86  return child.stdout
87}
88
89function makeCommand (file, args) {
90  var command, quote
91  command = file
92  if (args.length > 0) {
93    for (var i in args) {
94      command = command + ' '
95      if (args[i][0] === '-') {
96        command = command + args[i]
97      } else {
98        if (!quote) {
99          command = command + '"'
100          quote = true
101        }
102        command = command + args[i]
103        if (quote) {
104          if (args.length === (parseInt(i) + 1)) {
105            command = command + '"'
106          }
107        }
108      }
109    }
110  }
111  return command
112}
113
114function determineOS () {
115  var os = ''
116  var tmpVar = ''
117  if (process.env.OSTYPE) {
118    tmpVar = process.env.OSTYPE
119  } else if (process.env.OS) {
120    tmpVar = process.env.OS
121  } else {
122    // default is linux
123    tmpVar = 'linux'
124  }
125
126  if (startsWith(tmpVar, 'linux')) {
127    os = 'linux'
128  }
129  if (startsWith(tmpVar, 'win')) {
130    os = 'win'
131  }
132
133  return os
134}
135
136function unlinkFile (file) {
137  fs.unlinkSync(file)
138}
139
140module.exports = processExecSync
141