diff options
Diffstat (limited to 'deps/npm/node_modules/pacote/lib/util')
-rw-r--r-- | deps/npm/node_modules/pacote/lib/util/finished.js | 17 | ||||
-rw-r--r-- | deps/npm/node_modules/pacote/lib/util/git.js | 169 | ||||
-rw-r--r-- | deps/npm/node_modules/pacote/lib/util/gunzip-maybe.js | 24 | ||||
-rw-r--r-- | deps/npm/node_modules/pacote/lib/util/opt-check.js | 5 | ||||
-rw-r--r-- | deps/npm/node_modules/pacote/lib/util/pack-dir.js | 4 |
5 files changed, 128 insertions, 91 deletions
diff --git a/deps/npm/node_modules/pacote/lib/util/finished.js b/deps/npm/node_modules/pacote/lib/util/finished.js new file mode 100644 index 0000000000..6dadc8b5b3 --- /dev/null +++ b/deps/npm/node_modules/pacote/lib/util/finished.js @@ -0,0 +1,17 @@ +'use strict' + +const BB = require('bluebird') + +module.exports = function (child, hasExitCode = false) { + return BB.fromNode(function (cb) { + child.on('error', cb) + child.on(hasExitCode ? 'close' : 'end', function (exitCode) { + if (exitCode === undefined || exitCode === 0) { + cb() + } else { + let err = new Error('exited with error code: ' + exitCode) + cb(err) + } + }) + }) +} diff --git a/deps/npm/node_modules/pacote/lib/util/git.js b/deps/npm/node_modules/pacote/lib/util/git.js index a6162ceeba..9196212278 100644 --- a/deps/npm/node_modules/pacote/lib/util/git.js +++ b/deps/npm/node_modules/pacote/lib/util/git.js @@ -6,14 +6,16 @@ const cp = require('child_process') const execFileAsync = BB.promisify(cp.execFile, { multiArgs: true }) -const finished = BB.promisify(require('mississippi').finished) +const finished = require('./finished') const LRU = require('lru-cache') const optCheck = require('./opt-check') const osenv = require('osenv') const path = require('path') const pinflight = require('promise-inflight') +const promiseRetry = require('promise-retry') const uniqueFilename = require('unique-filename') const which = BB.promisify(require('which')) +const semver = require('semver') const GOOD_ENV_VARS = new Set([ 'GIT_ASKPASS', @@ -25,6 +27,23 @@ const GOOD_ENV_VARS = new Set([ 'GIT_SSL_NO_VERIFY' ]) +const GIT_TRANSIENT_ERRORS = [ + 'remote error: Internal Server Error', + 'The remote end hung up unexpectedly', + 'Connection timed out', + 'Operation timed out', + 'Failed to connect to .* Timed out', + 'Connection reset by peer', + 'SSL_ERROR_SYSCALL', + 'The requested URL returned error: 503' +].join('|') + +const GIT_TRANSIENT_ERROR_RE = new RegExp(GIT_TRANSIENT_ERRORS) + +function shouldRetry (error) { + return GIT_TRANSIENT_ERROR_RE.test(error) +} + const GIT_ = 'GIT_' let GITENV function gitEnv () { @@ -51,16 +70,14 @@ try { module.exports.clone = fullClone function fullClone (repo, committish, target, opts) { opts = optCheck(opts) - const gitArgs = ['clone', '-q', repo, target] + const gitArgs = ['clone', '--mirror', '-q', repo, path.join(target, '.git')] if (process.platform === 'win32') { gitArgs.push('--config', 'core.longpaths=true') } - return execGit(gitArgs, { - cwd: path.dirname(target) - }, opts).then(() => { - return committish && execGit(['checkout', committish], { - cwd: target - }) + return execGit(gitArgs, {cwd: target}).then(() => { + return execGit(['init'], {cwd: target}) + }).then(() => { + return execGit(['checkout', committish || 'HEAD'], {cwd: target}) }).then(() => { return updateSubmodules(target, opts) }).then(() => headSha(target, opts)) @@ -113,57 +130,51 @@ function revs (repo, opts) { return pinflight(`ls-remote:${repo}`, () => { return spawnGit(['ls-remote', '-h', '-t', repo], { env: gitEnv() - }, opts).then(child => { - let stdout = '' - let stderr = '' - child.stdout.on('data', d => { stdout += d }) - child.stderr.on('data', d => { stderr += d }) - return finished(child).catch(err => { - err.message = `Error while executing:\n${GITPATH} ls-remote -h -t ${repo}\n\n${stderr}\n${err.message}` - throw err - }).then(() => { - return stdout.split('\n').reduce((revs, line) => { - const split = line.split(/\s+/, 2) - if (split.length < 2) { return revs } - const sha = split[0].trim() - const ref = split[1].trim().match(/(?:refs\/[^/]+\/)?(.*)/)[1] - if (!ref) { return revs } // ??? - if (ref.endsWith(CARET_BRACES)) { return revs } // refs/tags/x^{} crap - const type = refType(line) - const doc = {sha, ref, type} - - revs.refs[ref] = doc - // We can check out shallow clones on specific SHAs if we have a ref - if (revs.shas[sha]) { - revs.shas[sha].push(ref) - } else { - revs.shas[sha] = [ref] - } + }, opts).then((stdout) => { + return stdout.split('\n').reduce((revs, line) => { + const split = line.split(/\s+/, 2) + if (split.length < 2) { return revs } + const sha = split[0].trim() + const ref = split[1].trim().match(/(?:refs\/[^/]+\/)?(.*)/)[1] + if (!ref) { return revs } // ??? + if (ref.endsWith(CARET_BRACES)) { return revs } // refs/tags/x^{} crap + const type = refType(line) + const doc = {sha, ref, type} - if (type === 'tag') { - const match = ref.match(/v?(\d+\.\d+\.\d+)$/) - if (match) { - revs.versions[match[1]] = doc - } - } + revs.refs[ref] = doc + // We can check out shallow clones on specific SHAs if we have a ref + if (revs.shas[sha]) { + revs.shas[sha].push(ref) + } else { + revs.shas[sha] = [ref] + } - return revs - }, {versions: {}, 'dist-tags': {}, refs: {}, shas: {}}) - }).then(revs => { - if (revs.refs.HEAD) { - const HEAD = revs.refs.HEAD - Object.keys(revs.versions).forEach(v => { - if (v.sha === HEAD.sha) { - revs['dist-tags'].HEAD = v - if (!revs.refs.latest) { - revs['dist-tags'].latest = revs.refs.HEAD - } - } - }) + if (type === 'tag') { + const match = ref.match(/v?(\d+\.\d+\.\d+(?:[-+].+)?)$/) + if (match && semver.valid(match[1], true)) { + revs.versions[semver.clean(match[1], true)] = doc + } } - REVS.set(repo, revs) + return revs - }) + }, {versions: {}, 'dist-tags': {}, refs: {}, shas: {}}) + }, err => { + err.message = `Error while executing:\n${GITPATH} ls-remote -h -t ${repo}\n\n${err.stderr}\n${err.message}` + throw err + }).then(revs => { + if (revs.refs.HEAD) { + const HEAD = revs.refs.HEAD + Object.keys(revs.versions).forEach(v => { + if (v.sha === HEAD.sha) { + revs['dist-tags'].HEAD = v + if (!revs.refs.latest) { + revs['dist-tags'].latest = revs.refs.HEAD + } + } + }) + } + REVS.set(repo, revs) + return revs }) }) } @@ -172,7 +183,18 @@ module.exports._exec = execGit function execGit (gitArgs, gitOpts, opts) { opts = optCheck(opts) return checkGit().then(gitPath => { - return execFileAsync(gitPath, gitArgs, mkOpts(gitOpts, opts)) + return promiseRetry((retry, number) => { + if (number !== 1) { + opts.log.silly('pacote', 'Retrying git command: ' + gitArgs.join(' ') + ' attempt # ' + number) + } + return execFileAsync(gitPath, gitArgs, mkOpts(gitOpts, opts)).catch((err) => { + if (shouldRetry(err)) { + retry(err) + } else { + throw err + } + }) + }, opts.retry) }) } @@ -180,7 +202,28 @@ module.exports._spawn = spawnGit function spawnGit (gitArgs, gitOpts, opts) { opts = optCheck(opts) return checkGit().then(gitPath => { - return cp.spawn(gitPath, gitArgs, mkOpts(gitOpts, opts)) + return promiseRetry((retry, number) => { + if (number !== 1) { + opts.log.silly('pacote', 'Retrying git command: ' + gitArgs.join(' ') + ' attempt # ' + number) + } + const child = cp.spawn(gitPath, gitArgs, mkOpts(gitOpts, opts)) + + let stdout = '' + let stderr = '' + child.stdout.on('data', d => { stdout += d }) + child.stderr.on('data', d => { stderr += d }) + + return finished(child, true).catch(err => { + if (shouldRetry(stderr)) { + retry(err) + } else { + err.stderr = stderr + throw err + } + }).then(() => { + return stdout + }) + }, opts.retry) }) } @@ -213,10 +256,10 @@ const REFS_HEADS = 'refs/heads/' const HEAD = 'HEAD' function refType (ref) { return ref.indexOf(REFS_TAGS) !== -1 - ? 'tag' - : ref.indexOf(REFS_HEADS) !== -1 - ? 'branch' - : ref.endsWith(HEAD) - ? 'head' - : 'other' + ? 'tag' + : ref.indexOf(REFS_HEADS) !== -1 + ? 'branch' + : ref.endsWith(HEAD) + ? 'head' + : 'other' } diff --git a/deps/npm/node_modules/pacote/lib/util/gunzip-maybe.js b/deps/npm/node_modules/pacote/lib/util/gunzip-maybe.js deleted file mode 100644 index 055de2921a..0000000000 --- a/deps/npm/node_modules/pacote/lib/util/gunzip-maybe.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' - -const duplex = require('mississippi').duplex -const through = require('mississippi').through -const zlib = require('zlib') - -function hasGzipHeader (c) { - return c[0] === 0x1F && c[1] === 0x8B && c[2] === 0x08 -} - -module.exports = gunzip -function gunzip () { - const stream = duplex() - const peeker = through((chunk, enc, cb) => { - const newStream = hasGzipHeader(chunk) - ? zlib.createGunzip() - : through() - stream.setReadable(newStream) - stream.setWritable(newStream) - stream.write(chunk) - }) - stream.setWritable(peeker) - return stream -} diff --git a/deps/npm/node_modules/pacote/lib/util/opt-check.js b/deps/npm/node_modules/pacote/lib/util/opt-check.js index 711f46c91a..d13a69e4dc 100644 --- a/deps/npm/node_modules/pacote/lib/util/opt-check.js +++ b/deps/npm/node_modules/pacote/lib/util/opt-check.js @@ -25,6 +25,7 @@ function PacoteOptions (opts) { this.proxy = opts.proxy this.noProxy = opts.noProxy this.registry = opts.registry || 'https://registry.npmjs.org' + this.resolved = opts.resolved this.retry = opts.retry // for npm-registry-client this.scope = opts.scope this.userAgent = opts.userAgent || `${pkg.name}@${pkg.version}/node@${process.version}+${process.arch} (${process.platform})` @@ -44,8 +45,8 @@ function PacoteOptions (opts) { this.fullMetadata = opts.fullMetadata this.alwaysAuth = opts.alwaysAuth this.includeDeprecated = opts.includeDeprecated == null - ? true - : opts.includeDeprecated + ? true + : opts.includeDeprecated this.dirPacker = opts.dirPacker || null diff --git a/deps/npm/node_modules/pacote/lib/util/pack-dir.js b/deps/npm/node_modules/pacote/lib/util/pack-dir.js index 7625f4faf8..62776692e1 100644 --- a/deps/npm/node_modules/pacote/lib/util/pack-dir.js +++ b/deps/npm/node_modules/pacote/lib/util/pack-dir.js @@ -14,8 +14,8 @@ function packDir (manifest, label, dir, target, opts) { opts = optCheck(opts) const packer = opts.dirPacker - ? BB.resolve(opts.dirPacker(manifest, dir)) - : mkPacker(dir) + ? BB.resolve(opts.dirPacker(manifest, dir)) + : mkPacker(dir) if (!opts.cache) { return packer.then(packer => pipe(packer, target)) |