1#!/usr/bin/env node
2
3'use strict'
4
5process.title = 'node-gyp'
6
7const envPaths = require('env-paths')
8const gyp = require('../')
9const log = require('../lib/log')
10const os = require('os')
11
12/**
13 * Process and execute the selected commands.
14 */
15
16const prog = gyp()
17let completed = false
18prog.parseArgv(process.argv)
19prog.devDir = prog.opts.devdir
20
21const homeDir = os.homedir()
22if (prog.devDir) {
23  prog.devDir = prog.devDir.replace(/^~/, homeDir)
24} else if (homeDir) {
25  prog.devDir = envPaths('node-gyp', { suffix: '' }).cache
26} else {
27  throw new Error(
28    "node-gyp requires that the user's home directory is specified " +
29    'in either of the environmental variables HOME or USERPROFILE. ' +
30    'Overide with: --devdir /path/to/.node-gyp')
31}
32
33if (prog.todo.length === 0) {
34  if (~process.argv.indexOf('-v') || ~process.argv.indexOf('--version')) {
35    log.stdout('v%s', prog.version)
36  } else {
37    log.stdout('%s', prog.usage())
38  }
39  process.exit(0)
40}
41
42log.info('it worked if it ends with', 'ok')
43log.verbose('cli', process.argv)
44log.info('using', 'node-gyp@%s', prog.version)
45log.info('using', 'node@%s | %s | %s', process.versions.node, process.platform, process.arch)
46
47/**
48 * Change dir if -C/--directory was passed.
49 */
50
51const dir = prog.opts.directory
52if (dir) {
53  const fs = require('fs')
54  try {
55    const stat = fs.statSync(dir)
56    if (stat.isDirectory()) {
57      log.info('chdir', dir)
58      process.chdir(dir)
59    } else {
60      log.warn('chdir', dir + ' is not a directory')
61    }
62  } catch (e) {
63    if (e.code === 'ENOENT') {
64      log.warn('chdir', dir + ' is not a directory')
65    } else {
66      log.warn('chdir', 'error during chdir() "%s"', e.message)
67    }
68  }
69}
70
71async function run () {
72  const command = prog.todo.shift()
73  if (!command) {
74    // done!
75    completed = true
76    log.info('ok')
77    return
78  }
79
80  try {
81    const args = await prog.commands[command.name](command.args) ?? []
82
83    if (command.name === 'list') {
84      if (args.length) {
85        args.forEach((version) => log.stdout(version))
86      } else {
87        log.stdout('No node development files installed. Use `node-gyp install` to install a version.')
88      }
89    } else if (args.length >= 1) {
90      log.stdout(...args.slice(1))
91    }
92
93    // now run the next command in the queue
94    return run()
95  } catch (err) {
96    log.error(command.name + ' error')
97    log.error('stack', err.stack)
98    errorMessage()
99    log.error('not ok')
100    return process.exit(1)
101  }
102}
103
104process.on('exit', function (code) {
105  if (!completed && !code) {
106    log.error('Completion callback never invoked!')
107    issueMessage()
108    process.exit(6)
109  }
110})
111
112process.on('uncaughtException', function (err) {
113  log.error('UNCAUGHT EXCEPTION')
114  log.error('stack', err.stack)
115  issueMessage()
116  process.exit(7)
117})
118
119function errorMessage () {
120  // copied from npm's lib/utils/error-handler.js
121  const os = require('os')
122  log.error('System', os.type() + ' ' + os.release())
123  log.error('command', process.argv
124    .map(JSON.stringify).join(' '))
125  log.error('cwd', process.cwd())
126  log.error('node -v', process.version)
127  log.error('node-gyp -v', 'v' + prog.package.version)
128}
129
130function issueMessage () {
131  errorMessage()
132  log.error('', ['Node-gyp failed to build your package.',
133    'Try to update npm and/or node-gyp and if it does not help file an issue with the package author.'
134  ].join('\n'))
135}
136
137// start running the given commands!
138run()
139