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