1const spawn = require('@npmcli/promise-spawn') 2const promiseRetry = require('promise-retry') 3const log = require('proc-log') 4const makeError = require('./make-error.js') 5const makeOpts = require('./opts.js') 6 7module.exports = (gitArgs, opts = {}) => { 8 const whichGit = require('./which.js') 9 const gitPath = whichGit(opts) 10 11 if (gitPath instanceof Error) { 12 return Promise.reject(gitPath) 13 } 14 15 // undocumented option, mostly only here for tests 16 const args = opts.allowReplace || gitArgs[0] === '--no-replace-objects' 17 ? gitArgs 18 : ['--no-replace-objects', ...gitArgs] 19 20 let retryOpts = opts.retry 21 if (retryOpts === null || retryOpts === undefined) { 22 retryOpts = { 23 retries: opts.fetchRetries || 2, 24 factor: opts.fetchRetryFactor || 10, 25 maxTimeout: opts.fetchRetryMaxtimeout || 60000, 26 minTimeout: opts.fetchRetryMintimeout || 1000, 27 } 28 } 29 return promiseRetry((retryFn, number) => { 30 if (number !== 1) { 31 log.silly('git', `Retrying git command: ${ 32 args.join(' ')} attempt # ${number}`) 33 } 34 35 return spawn(gitPath, args, makeOpts(opts)) 36 .catch(er => { 37 const gitError = makeError(er) 38 if (!gitError.shouldRetry(number)) { 39 throw gitError 40 } 41 retryFn(gitError) 42 }) 43 }, retryOpts) 44} 45