• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2
3const BB = require('bluebird')
4
5const exec = require('child_process').execFile
6const spawn = require('./spawn')
7const npm = require('../npm.js')
8const which = require('which')
9const git = npm.config.get('git')
10const assert = require('assert')
11const log = require('npmlog')
12const noProgressTillDone = require('./no-progress-while-running.js').tillDone
13
14exports.spawn = spawnGit
15exports.exec = BB.promisify(execGit)
16exports.chainableExec = chainableExec
17exports.whichAndExec = whichAndExec
18
19function prefixGitArgs () {
20  return process.platform === 'win32' ? ['-c', 'core.longpaths=true'] : []
21}
22
23function execGit (args, options, cb) {
24  log.info('git', args)
25  const fullArgs = prefixGitArgs().concat(args || [])
26  return exec(git, fullArgs, options, noProgressTillDone(cb))
27}
28
29function spawnGit (args, options) {
30  log.info('git', args)
31  // If we're already in a git command (eg, running test as an exec
32  // line in an interactive rebase) then these environment variables
33  // will force git to operate on the current project, instead of
34  // checking out/fetching/etc. whatever the user actually intends.
35  options.env = options.env || Object.keys(process.env)
36    .filter(k => !/^GIT/.test(k))
37    .reduce((set, k) => {
38      set[k] = process.env[k]
39      return set
40    }, {})
41  return spawn(git, prefixGitArgs().concat(args || []), options)
42}
43
44function chainableExec () {
45  var args = Array.prototype.slice.call(arguments)
46  return [execGit].concat(args)
47}
48
49function whichAndExec (args, options, cb) {
50  assert.equal(typeof cb, 'function', 'no callback provided')
51  // check for git
52  which(git, function (err) {
53    if (err) {
54      err.code = 'ENOGIT'
55      return cb(err)
56    }
57
58    execGit(args, options, cb)
59  })
60}
61