pacote 7.5.1 → 7.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,46 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ <a name="7.6.1"></a>
6
+ ## [7.6.1](https://github.com/zkat/pacote/compare/v7.6.0...v7.6.1) (2018-03-08)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **standard:** update to new standard rules ([bb52d02](https://github.com/zkat/pacote/commit/bb52d02))
12
+
13
+
14
+
15
+ <a name="7.6.0"></a>
16
+ # [7.6.0](https://github.com/zkat/pacote/compare/v7.5.3...v7.6.0) (2018-03-08)
17
+
18
+
19
+ ### Features
20
+
21
+ * **git:** added retry logic for all git operations. ([#136](https://github.com/zkat/pacote/issues/136)) ([425c58d](https://github.com/zkat/pacote/commit/425c58d))
22
+
23
+
24
+
25
+ <a name="7.5.3"></a>
26
+ ## [7.5.3](https://github.com/zkat/pacote/compare/v7.5.2...v7.5.3) (2018-03-02)
27
+
28
+
29
+ ### Bug Fixes
30
+
31
+ * **tarball:** stop dropping stream errors on the floor ([3db03c2](https://github.com/zkat/pacote/commit/3db03c2))
32
+
33
+
34
+
35
+ <a name="7.5.2"></a>
36
+ ## [7.5.2](https://github.com/zkat/pacote/compare/v7.5.1...v7.5.2) (2018-03-02)
37
+
38
+
39
+ ### Bug Fixes
40
+
41
+ * **console:** remove spurious debugging console.log :< ([5b8b509](https://github.com/zkat/pacote/commit/5b8b509))
42
+
43
+
44
+
5
45
  <a name="7.5.1"></a>
6
46
  ## [7.5.1](https://github.com/zkat/pacote/compare/v7.5.0...v7.5.1) (2018-03-01)
7
47
 
package/extract.js CHANGED
@@ -24,27 +24,27 @@ function extract (spec, dest, opts) {
24
24
  return withTarballStream(spec, opts, stream => {
25
25
  return tryExtract(spec, stream, dest, opts)
26
26
  })
27
- .then(() => {
28
- if (!opts.resolved) {
29
- const pjson = path.join(dest, 'package.json')
30
- return readFileAsync(pjson, 'utf8')
31
- .then(str => truncateAsync(pjson)
32
- .then(() => appendFileAsync(pjson, str.replace(
33
- /}\s*$/,
34
- `\n,"_resolved": ${
35
- JSON.stringify(opts.resolved || '')
36
- }\n,"_integrity": ${
37
- JSON.stringify(opts.integrity || '')
38
- }\n,"_from": ${
39
- JSON.stringify(spec.toString())
40
- }\n}`
41
- ))))
42
- }
43
- })
44
- .then(() => opts.log.silly(
45
- 'extract',
46
- `${spec} extracted to ${dest} (${Date.now() - startTime}ms)`
47
- ))
27
+ .then(() => {
28
+ if (!opts.resolved) {
29
+ const pjson = path.join(dest, 'package.json')
30
+ return readFileAsync(pjson, 'utf8')
31
+ .then(str => truncateAsync(pjson)
32
+ .then(() => appendFileAsync(pjson, str.replace(
33
+ /}\s*$/,
34
+ `\n,"_resolved": ${
35
+ JSON.stringify(opts.resolved || '')
36
+ }\n,"_integrity": ${
37
+ JSON.stringify(opts.integrity || '')
38
+ }\n,"_from": ${
39
+ JSON.stringify(spec.toString())
40
+ }\n}`
41
+ ))))
42
+ }
43
+ })
44
+ .then(() => opts.log.silly(
45
+ 'extract',
46
+ `${spec} extracted to ${dest} (${Date.now() - startTime}ms)`
47
+ ))
48
48
  }
49
49
 
50
50
  function tryExtract (spec, tarStream, dest, opts) {
@@ -52,19 +52,19 @@ function tryExtract (spec, tarStream, dest, opts) {
52
52
  tarStream.on('error', reject)
53
53
  setImmediate(resolve)
54
54
  })
55
- .then(() => rimraf(dest))
56
- .then(() => mkdirp(dest))
57
- .then(() => new BB((resolve, reject) => {
58
- const xtractor = extractStream(spec, dest, opts)
59
- tarStream.on('error', reject)
60
- xtractor.on('error', reject)
61
- xtractor.on('close', resolve)
62
- tarStream.pipe(xtractor)
63
- }))
64
- .catch(err => {
65
- if (err.code === 'EINTEGRITY') {
66
- err.message = `Verification failed while extracting ${spec}:\n${err.message}`
67
- }
68
- throw err
69
- })
55
+ .then(() => rimraf(dest))
56
+ .then(() => mkdirp(dest))
57
+ .then(() => new BB((resolve, reject) => {
58
+ const xtractor = extractStream(spec, dest, opts)
59
+ tarStream.on('error', reject)
60
+ xtractor.on('error', reject)
61
+ xtractor.on('close', resolve)
62
+ tarStream.pipe(xtractor)
63
+ }))
64
+ .catch(err => {
65
+ if (err.code === 'EINTEGRITY') {
66
+ err.message = `Verification failed while extracting ${spec}:\n${err.message}`
67
+ }
68
+ throw err
69
+ })
70
70
  }
@@ -52,13 +52,13 @@ Fetcher.impl(fetchFile, {
52
52
  } else {
53
53
  let integrity
54
54
  const cacheWriter = !opts.cache
55
- ? BB.resolve(null)
56
- : (pipe(
57
- fs.createReadStream(src),
58
- cacache.put.stream(opts.cache, `pacote:tarball:${src}`, {
59
- integrity: opts.integrity
60
- }).on('integrity', d => { integrity = d })
61
- ))
55
+ ? BB.resolve(null)
56
+ : (pipe(
57
+ fs.createReadStream(src),
58
+ cacache.put.stream(opts.cache, `pacote:tarball:${src}`, {
59
+ integrity: opts.integrity
60
+ }).on('integrity', d => { integrity = d })
61
+ ))
62
62
  return cacheWriter.then(() => {
63
63
  if (integrity) { stream.emit('integrity', integrity) }
64
64
  return pipe(fs.createReadStream(src), stream)
@@ -135,16 +135,16 @@ function resolve (url, spec, name, opts) {
135
135
  const isSemver = !!spec.gitRange
136
136
  return git.revs(url, opts).then(remoteRefs => {
137
137
  return isSemver
138
- ? pickManifest({
139
- versions: remoteRefs.versions,
140
- 'dist-tags': remoteRefs['dist-tags'],
141
- name: name
142
- }, spec.gitRange, opts)
143
- : remoteRefs
144
- ? BB.resolve(
145
- remoteRefs.refs[spec.gitCommittish] || remoteRefs.refs[remoteRefs.shas[spec.gitCommittish]]
146
- )
147
- : null
138
+ ? pickManifest({
139
+ versions: remoteRefs.versions,
140
+ 'dist-tags': remoteRefs['dist-tags'],
141
+ name: name
142
+ }, spec.gitRange, opts)
143
+ : remoteRefs
144
+ ? BB.resolve(
145
+ remoteRefs.refs[spec.gitCommittish] || remoteRefs.refs[remoteRefs.shas[spec.gitCommittish]]
146
+ )
147
+ : null
148
148
  })
149
149
  }
150
150
 
@@ -68,12 +68,12 @@ function logRequest (uri, res, startTime, opts) {
68
68
 
69
69
  function getCacheMode (opts) {
70
70
  return opts.offline
71
- ? 'only-if-cached'
72
- : opts.preferOffline
73
- ? 'force-cache'
74
- : opts.preferOnline
75
- ? 'no-cache'
76
- : 'default'
71
+ ? 'only-if-cached'
72
+ : opts.preferOffline
73
+ ? 'force-cache'
74
+ : opts.preferOnline
75
+ ? 'no-cache'
76
+ : 'default'
77
77
  }
78
78
 
79
79
  function getHeaders (uri, registry, opts) {
@@ -28,8 +28,8 @@ function manifest (spec, opts) {
28
28
 
29
29
  function metadataUrl (registry, name) {
30
30
  const normalized = registry.slice(-1) !== '/'
31
- ? registry + '/'
32
- : registry
31
+ ? registry + '/'
32
+ : registry
33
33
  return url.resolve(normalized, name)
34
34
  }
35
35
 
@@ -60,20 +60,20 @@ function fromManifest (manifest, spec, opts) {
60
60
  integrity: manifest._integrity,
61
61
  algorithms: [
62
62
  manifest._integrity
63
- ? ssri.parse(manifest._integrity).pickAlgorithm()
64
- : 'sha1'
63
+ ? ssri.parse(manifest._integrity).pickAlgorithm()
64
+ : 'sha1'
65
65
  ],
66
66
  spec
67
67
  }, opts))
68
- .then(res => {
69
- const hash = res.headers.get('x-local-cache-hash')
70
- if (hash) {
71
- stream.emit('integrity', decodeURIComponent(hash))
72
- }
73
- res.body.on('error', err => stream.emit('error', err))
74
- res.body.pipe(stream)
75
- })
76
- .catch(err => stream.emit('error', err))
68
+ .then(res => {
69
+ const hash = res.headers.get('x-local-cache-hash')
70
+ if (hash) {
71
+ stream.emit('integrity', decodeURIComponent(hash))
72
+ }
73
+ res.body.on('error', err => stream.emit('error', err))
74
+ res.body.pipe(stream)
75
+ })
76
+ .catch(err => stream.emit('error', err))
77
77
  return stream
78
78
  }
79
79
 
@@ -38,8 +38,8 @@ function finalizeManifest (pkg, spec, opts) {
38
38
  opts = optCheck(opts)
39
39
 
40
40
  const cachedManifest = (opts.cache && key && !opts.preferOnline && !opts.fullMetadata)
41
- ? cacache.get.info(opts.cache, key, opts)
42
- : BB.resolve(null)
41
+ ? cacache.get.info(opts.cache, key, opts)
42
+ : BB.resolve(null)
43
43
 
44
44
  return cachedManifest.then(cached => {
45
45
  if (cached && cached.metadata.manifest) {
@@ -47,8 +47,8 @@ function finalizeManifest (pkg, spec, opts) {
47
47
  } else {
48
48
  return tarballedProps(pkg, spec, opts).then(props => {
49
49
  return pkg && pkg.name
50
- ? new Manifest(pkg, props, opts.fullMetadata)
51
- : new Manifest(props, null, opts.fullMetadata)
50
+ ? new Manifest(pkg, props, opts.fullMetadata)
51
+ : new Manifest(props, null, opts.fullMetadata)
52
52
  }).then(manifest => {
53
53
  const cacheKey = key || finalKey(manifest, spec)
54
54
  if (!opts.cache || !cacheKey) {
@@ -169,8 +169,8 @@ function tarballedProps (pkg, spec, opts) {
169
169
  // to add to bin
170
170
  if (paths && paths.length) {
171
171
  const dirBin = mani
172
- ? (mani && mani.directories && mani.directories.bin)
173
- : (pkg && pkg.directories && pkg.directories.bin)
172
+ ? (mani && mani.directories && mani.directories.bin)
173
+ : (pkg && pkg.directories && pkg.directories.bin)
174
174
  if (dirBin) {
175
175
  extraProps.bin = {}
176
176
  paths.forEach(filePath => {
package/lib/util/git.js CHANGED
@@ -12,6 +12,7 @@ const optCheck = require('./opt-check')
12
12
  const osenv = require('osenv')
13
13
  const path = require('path')
14
14
  const pinflight = require('promise-inflight')
15
+ const promiseRetry = require('promise-retry')
15
16
  const uniqueFilename = require('unique-filename')
16
17
  const which = BB.promisify(require('which'))
17
18
  const semver = require('semver')
@@ -26,6 +27,23 @@ const GOOD_ENV_VARS = new Set([
26
27
  'GIT_SSL_NO_VERIFY'
27
28
  ])
28
29
 
30
+ const GIT_TRANSIENT_ERRORS = [
31
+ 'remote error: Internal Server Error',
32
+ 'The remote end hung up unexpectedly',
33
+ 'Connection timed out',
34
+ 'Operation timed out',
35
+ 'Failed to connect to .* Timed out',
36
+ 'Connection reset by peer',
37
+ 'SSL_ERROR_SYSCALL',
38
+ 'The requested URL returned error: 503'
39
+ ].join('|')
40
+
41
+ const GIT_TRANSIENT_ERROR_RE = new RegExp(GIT_TRANSIENT_ERRORS)
42
+
43
+ function shouldRetry (error) {
44
+ return GIT_TRANSIENT_ERROR_RE.test(error)
45
+ }
46
+
29
47
  const GIT_ = 'GIT_'
30
48
  let GITENV
31
49
  function gitEnv () {
@@ -114,57 +132,51 @@ function revs (repo, opts) {
114
132
  return pinflight(`ls-remote:${repo}`, () => {
115
133
  return spawnGit(['ls-remote', '-h', '-t', repo], {
116
134
  env: gitEnv()
117
- }, opts).then(child => {
118
- let stdout = ''
119
- let stderr = ''
120
- child.stdout.on('data', d => { stdout += d })
121
- child.stderr.on('data', d => { stderr += d })
122
- return finished(child).catch(err => {
123
- err.message = `Error while executing:\n${GITPATH} ls-remote -h -t ${repo}\n\n${stderr}\n${err.message}`
124
- throw err
125
- }).then(() => {
126
- return stdout.split('\n').reduce((revs, line) => {
127
- const split = line.split(/\s+/, 2)
128
- if (split.length < 2) { return revs }
129
- const sha = split[0].trim()
130
- const ref = split[1].trim().match(/(?:refs\/[^/]+\/)?(.*)/)[1]
131
- if (!ref) { return revs } // ???
132
- if (ref.endsWith(CARET_BRACES)) { return revs } // refs/tags/x^{} crap
133
- const type = refType(line)
134
- const doc = {sha, ref, type}
135
-
136
- revs.refs[ref] = doc
137
- // We can check out shallow clones on specific SHAs if we have a ref
138
- if (revs.shas[sha]) {
139
- revs.shas[sha].push(ref)
140
- } else {
141
- revs.shas[sha] = [ref]
142
- }
135
+ }, opts).then((stdout) => {
136
+ return stdout.split('\n').reduce((revs, line) => {
137
+ const split = line.split(/\s+/, 2)
138
+ if (split.length < 2) { return revs }
139
+ const sha = split[0].trim()
140
+ const ref = split[1].trim().match(/(?:refs\/[^/]+\/)?(.*)/)[1]
141
+ if (!ref) { return revs } // ???
142
+ if (ref.endsWith(CARET_BRACES)) { return revs } // refs/tags/x^{} crap
143
+ const type = refType(line)
144
+ const doc = {sha, ref, type}
143
145
 
144
- if (type === 'tag') {
145
- const match = ref.match(/v?(\d+\.\d+\.\d+(?:[-+].+)?)$/)
146
- if (match && semver.valid(match[1], true)) {
147
- revs.versions[semver.clean(match[1], true)] = doc
148
- }
149
- }
146
+ revs.refs[ref] = doc
147
+ // We can check out shallow clones on specific SHAs if we have a ref
148
+ if (revs.shas[sha]) {
149
+ revs.shas[sha].push(ref)
150
+ } else {
151
+ revs.shas[sha] = [ref]
152
+ }
150
153
 
151
- return revs
152
- }, {versions: {}, 'dist-tags': {}, refs: {}, shas: {}})
153
- }).then(revs => {
154
- if (revs.refs.HEAD) {
155
- const HEAD = revs.refs.HEAD
156
- Object.keys(revs.versions).forEach(v => {
157
- if (v.sha === HEAD.sha) {
158
- revs['dist-tags'].HEAD = v
159
- if (!revs.refs.latest) {
160
- revs['dist-tags'].latest = revs.refs.HEAD
161
- }
162
- }
163
- })
154
+ if (type === 'tag') {
155
+ const match = ref.match(/v?(\d+\.\d+\.\d+(?:[-+].+)?)$/)
156
+ if (match && semver.valid(match[1], true)) {
157
+ revs.versions[semver.clean(match[1], true)] = doc
158
+ }
164
159
  }
165
- REVS.set(repo, revs)
160
+
166
161
  return revs
167
- })
162
+ }, {versions: {}, 'dist-tags': {}, refs: {}, shas: {}})
163
+ }, err => {
164
+ err.message = `Error while executing:\n${GITPATH} ls-remote -h -t ${repo}\n\n${err.stderr}\n${err.message}`
165
+ throw err
166
+ }).then(revs => {
167
+ if (revs.refs.HEAD) {
168
+ const HEAD = revs.refs.HEAD
169
+ Object.keys(revs.versions).forEach(v => {
170
+ if (v.sha === HEAD.sha) {
171
+ revs['dist-tags'].HEAD = v
172
+ if (!revs.refs.latest) {
173
+ revs['dist-tags'].latest = revs.refs.HEAD
174
+ }
175
+ }
176
+ })
177
+ }
178
+ REVS.set(repo, revs)
179
+ return revs
168
180
  })
169
181
  })
170
182
  }
@@ -173,7 +185,18 @@ module.exports._exec = execGit
173
185
  function execGit (gitArgs, gitOpts, opts) {
174
186
  opts = optCheck(opts)
175
187
  return checkGit().then(gitPath => {
176
- return execFileAsync(gitPath, gitArgs, mkOpts(gitOpts, opts))
188
+ return promiseRetry((retry, number) => {
189
+ if (number !== 1) {
190
+ opts.log.silly('pacote', 'Retrying git command: ' + gitArgs.join(' ') + ' attempt # ' + number)
191
+ }
192
+ return execFileAsync(gitPath, gitArgs, mkOpts(gitOpts, opts)).catch((err) => {
193
+ if (shouldRetry(err)) {
194
+ retry(err)
195
+ } else {
196
+ throw err
197
+ }
198
+ })
199
+ }, opts.retry)
177
200
  })
178
201
  }
179
202
 
@@ -181,7 +204,28 @@ module.exports._spawn = spawnGit
181
204
  function spawnGit (gitArgs, gitOpts, opts) {
182
205
  opts = optCheck(opts)
183
206
  return checkGit().then(gitPath => {
184
- return cp.spawn(gitPath, gitArgs, mkOpts(gitOpts, opts))
207
+ return promiseRetry((retry, number) => {
208
+ if (number !== 1) {
209
+ opts.log.silly('pacote', 'Retrying git command: ' + gitArgs.join(' ') + ' attempt # ' + number)
210
+ }
211
+ const child = cp.spawn(gitPath, gitArgs, mkOpts(gitOpts, opts))
212
+
213
+ let stdout = ''
214
+ let stderr = ''
215
+ child.stdout.on('data', d => { stdout += d })
216
+ child.stderr.on('data', d => { stderr += d })
217
+
218
+ return finished(child).catch(err => {
219
+ if (shouldRetry(stderr)) {
220
+ retry(err)
221
+ } else {
222
+ err.stderr = stderr
223
+ throw err
224
+ }
225
+ }).then(() => {
226
+ return stdout
227
+ })
228
+ }, opts.retry)
185
229
  })
186
230
  }
187
231
 
@@ -214,10 +258,10 @@ const REFS_HEADS = 'refs/heads/'
214
258
  const HEAD = 'HEAD'
215
259
  function refType (ref) {
216
260
  return ref.indexOf(REFS_TAGS) !== -1
217
- ? 'tag'
218
- : ref.indexOf(REFS_HEADS) !== -1
219
- ? 'branch'
220
- : ref.endsWith(HEAD)
221
- ? 'head'
222
- : 'other'
261
+ ? 'tag'
262
+ : ref.indexOf(REFS_HEADS) !== -1
263
+ ? 'branch'
264
+ : ref.endsWith(HEAD)
265
+ ? 'head'
266
+ : 'other'
223
267
  }
@@ -45,8 +45,8 @@ function PacoteOptions (opts) {
45
45
  this.fullMetadata = opts.fullMetadata
46
46
  this.alwaysAuth = opts.alwaysAuth
47
47
  this.includeDeprecated = opts.includeDeprecated == null
48
- ? true
49
- : opts.includeDeprecated
48
+ ? true
49
+ : opts.includeDeprecated
50
50
 
51
51
  this.dirPacker = opts.dirPacker || null
52
52
 
@@ -14,8 +14,8 @@ function packDir (manifest, label, dir, target, opts) {
14
14
  opts = optCheck(opts)
15
15
 
16
16
  const packer = opts.dirPacker
17
- ? BB.resolve(opts.dirPacker(manifest, dir))
18
- : mkPacker(dir)
17
+ ? BB.resolve(opts.dirPacker(manifest, dir))
18
+ : mkPacker(dir)
19
19
 
20
20
  if (!opts.cache) {
21
21
  return packer.then(packer => pipe(packer, target))
@@ -27,108 +27,107 @@ function withTarballStream (spec, opts, streamHandler) {
27
27
  opts.resolved &&
28
28
  opts.resolved.startsWith('file:')
29
29
  )
30
- ? BB.try(() => {
30
+ ? BB.try(() => {
31
31
  // NOTE - this is a special shortcut! Packages installed as files do not
32
32
  // have a `resolved` field -- this specific case only occurs when you have,
33
33
  // say, a git dependency or a registry dependency that you've packaged into
34
34
  // a local file, and put that file: spec in the `resolved` field.
35
- opts.log.silly('pacote', `trying ${spec} by local file: ${opts.resolved}`)
36
- const file = path.resolve(opts.where || '.', opts.resolved.substr(5))
37
- return statAsync(file)
38
- .then(() => {
39
- const verifier = ssri.integrityStream({integrity: opts.integrity})
40
- const stream = fs.createReadStream(file)
41
- .on('error', err => verifier.emit('error', err))
42
- .pipe(verifier)
43
- return streamHandler(stream)
44
- })
45
- .catch(err => {
46
- if (err.code === 'EINTEGRITY') {
47
- opts.log.warn('pacote', `EINTEGRITY while extracting ${spec} from ${file}.You will have to recreate the file.`)
48
- opts.log.verbose('pacote', `EINTEGRITY for ${spec}: ${err.message}`)
49
- }
50
- throw err
35
+ opts.log.silly('pacote', `trying ${spec} by local file: ${opts.resolved}`)
36
+ const file = path.resolve(opts.where || '.', opts.resolved.substr(5))
37
+ return statAsync(file)
38
+ .then(() => {
39
+ const verifier = ssri.integrityStream({integrity: opts.integrity})
40
+ const stream = fs.createReadStream(file)
41
+ .on('error', err => verifier.emit('error', err))
42
+ .pipe(verifier)
43
+ return streamHandler(stream)
44
+ })
45
+ .catch(err => {
46
+ if (err.code === 'EINTEGRITY') {
47
+ opts.log.warn('pacote', `EINTEGRITY while extracting ${spec} from ${file}.You will have to recreate the file.`)
48
+ opts.log.verbose('pacote', `EINTEGRITY for ${spec}: ${err.message}`)
49
+ }
50
+ throw err
51
+ })
51
52
  })
52
- })
53
- : BB.reject(Object.assign(new Error('no file!'), {code: 'ENOENT'}))
53
+ : BB.reject(Object.assign(new Error('no file!'), {code: 'ENOENT'}))
54
54
 
55
55
  const tryDigest = tryFile
56
- .catch(err => {
57
- if (
58
- opts.preferOnline ||
56
+ .catch(err => {
57
+ if (
58
+ opts.preferOnline ||
59
59
  !opts.cache ||
60
60
  !opts.integrity ||
61
61
  !RETRIABLE_ERRORS.has(err.code)
62
- ) {
63
- throw err
64
- } else {
65
- opts.log.silly('tarball', `trying ${spec} by hash: ${opts.integrity}`)
66
- const stream = cacache.get.stream.byDigest(
67
- opts.cache, opts.integrity, opts
68
- )
69
- stream.once('error', err => stream.on('newListener', (ev, l) => {
70
- if (ev === 'error') { l(err) }
71
- }))
72
- return streamHandler(stream)
73
- .catch(err => {
74
- if (err.code === 'EINTEGRITY' || err.code === 'Z_DATA_ERROR') {
75
- opts.log.warn('tarball', `cached data for ${spec} (${opts.integrity}) seems to be corrupted. Refreshing cache.`)
76
- return cleanUpCached(opts.cache, opts.integrity, opts)
77
- .then(() => { throw err })
78
- } else {
79
- throw err
80
- }
81
- })
82
- }
83
- })
62
+ ) {
63
+ throw err
64
+ } else {
65
+ opts.log.silly('tarball', `trying ${spec} by hash: ${opts.integrity}`)
66
+ const stream = cacache.get.stream.byDigest(
67
+ opts.cache, opts.integrity, opts
68
+ )
69
+ stream.once('error', err => stream.on('newListener', (ev, l) => {
70
+ if (ev === 'error') { l(err) }
71
+ }))
72
+ return streamHandler(stream)
73
+ .catch(err => {
74
+ if (err.code === 'EINTEGRITY' || err.code === 'Z_DATA_ERROR') {
75
+ opts.log.warn('tarball', `cached data for ${spec} (${opts.integrity}) seems to be corrupted. Refreshing cache.`)
76
+ return cleanUpCached(opts.cache, opts.integrity, opts)
77
+ .then(() => { throw err })
78
+ } else {
79
+ throw err
80
+ }
81
+ })
82
+ }
83
+ })
84
84
 
85
85
  const trySpec = tryDigest
86
- .catch(err => {
87
- if (!RETRIABLE_ERRORS.has(err.code)) {
86
+ .catch(err => {
87
+ if (!RETRIABLE_ERRORS.has(err.code)) {
88
88
  // If it's not one of our retriable errors, bail out and give up.
89
- throw err
90
- } else {
91
- opts.log.silly(
92
- 'tarball',
93
- `no local data for ${spec}. Extracting by manifest.`
94
- )
95
- return BB.resolve(retry((tryAgain, attemptNum) => {
96
- const tardata = fetch.tarball(spec, opts)
97
- if (!opts.resolved) {
98
- tardata.on('manifest', m => {
99
- opts.resolved = m._resolved
100
- })
101
- tardata.on('integrity', i => {
102
- opts.integrity = i
103
- })
104
- }
105
- tardata.on('error', err => console.error('ERROR:', err))
106
- return BB.try(() => streamHandler(tardata))
107
- .catch(err => {
108
- // Retry once if we have a cache, to clear up any weird conditions.
109
- // Don't retry network errors, though -- make-fetch-happen has already
110
- // taken care of making sure we're all set on that front.
111
- if (opts.cache && err.code && !err.code.match(/^E\d{3}$/)) {
112
- if (err.code === 'EINTEGRITY' || err.code === 'Z_DATA_ERROR') {
113
- opts.log.warn('tarball', `tarball data for ${spec} (${opts.integrity}) seems to be corrupted. Trying one more time.`)
114
- }
115
- return cleanUpCached(opts.cache, err.sri, opts)
116
- .then(() => tryAgain(err))
117
- } else {
118
- throw err
89
+ throw err
90
+ } else {
91
+ opts.log.silly(
92
+ 'tarball',
93
+ `no local data for ${spec}. Extracting by manifest.`
94
+ )
95
+ return BB.resolve(retry((tryAgain, attemptNum) => {
96
+ const tardata = fetch.tarball(spec, opts)
97
+ if (!opts.resolved) {
98
+ tardata.on('manifest', m => {
99
+ opts.resolved = m._resolved
100
+ })
101
+ tardata.on('integrity', i => {
102
+ opts.integrity = i
103
+ })
119
104
  }
120
- })
121
- }, {retries: 1}))
122
- }
123
- })
105
+ return BB.try(() => streamHandler(tardata))
106
+ .catch(err => {
107
+ // Retry once if we have a cache, to clear up any weird conditions.
108
+ // Don't retry network errors, though -- make-fetch-happen has already
109
+ // taken care of making sure we're all set on that front.
110
+ if (opts.cache && err.code && !err.code.match(/^E\d{3}$/)) {
111
+ if (err.code === 'EINTEGRITY' || err.code === 'Z_DATA_ERROR') {
112
+ opts.log.warn('tarball', `tarball data for ${spec} (${opts.integrity}) seems to be corrupted. Trying one more time.`)
113
+ }
114
+ return cleanUpCached(opts.cache, err.sri, opts)
115
+ .then(() => tryAgain(err))
116
+ } else {
117
+ throw err
118
+ }
119
+ })
120
+ }, {retries: 1}))
121
+ }
122
+ })
124
123
 
125
124
  return trySpec
126
- .catch(err => {
127
- if (err.code === 'EINTEGRITY') {
128
- err.message = `Verification failed while extracting ${spec}:\n${err.message}`
129
- }
130
- throw err
131
- })
125
+ .catch(err => {
126
+ if (err.code === 'EINTEGRITY') {
127
+ err.message = `Verification failed while extracting ${spec}:\n${err.message}`
128
+ }
129
+ throw err
130
+ })
132
131
  }
133
132
 
134
133
  function cleanUpCached (cachePath, integrity, opts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pacote",
3
- "version": "7.5.1",
3
+ "version": "7.6.1",
4
4
  "description": "JavaScript package downloader",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -48,7 +48,7 @@
48
48
  "lru-cache": "^4.1.1",
49
49
  "make-fetch-happen": "^2.6.0",
50
50
  "minimatch": "^3.0.4",
51
- "mississippi": "^2.0.0",
51
+ "mississippi": "^3.0.0",
52
52
  "mkdirp": "^0.5.1",
53
53
  "normalize-package-data": "^2.4.0",
54
54
  "npm-package-arg": "^6.0.0",
@@ -62,19 +62,19 @@
62
62
  "safe-buffer": "^5.1.1",
63
63
  "semver": "^5.5.0",
64
64
  "ssri": "^5.2.4",
65
- "tar": "^4.3.3",
65
+ "tar": "^4.4.0",
66
66
  "unique-filename": "^1.1.0",
67
67
  "which": "^1.3.0"
68
68
  },
69
69
  "devDependencies": {
70
- "nock": "^9.1.6",
70
+ "nock": "^9.2.3",
71
71
  "npmlog": "^4.1.2",
72
72
  "nyc": "^11.4.1",
73
73
  "require-inject": "^1.4.2",
74
- "standard": "^10.0.3",
74
+ "standard": "^11.0.0",
75
75
  "standard-version": "^4.3.0",
76
76
  "tacks": "^1.2.6",
77
- "tap": "^11.1.0",
77
+ "tap": "^11.1.2",
78
78
  "tar-stream": "^1.5.5",
79
79
  "weallbehave": "^1.2.0",
80
80
  "weallcontribute": "^1.0.7"
package/tarball.js CHANGED
@@ -45,6 +45,7 @@ function tarballStream (spec, opts) {
45
45
  })
46
46
  }
47
47
  })
48
+ .catch(err => output.emit('error', err))
48
49
  return output
49
50
  }
50
51
 
@@ -53,14 +54,14 @@ function tarballToFile (spec, dest, opts) {
53
54
  opts = optCheck(opts)
54
55
  spec = npa(spec, opts.where)
55
56
  return mkdirp(path.dirname(dest))
56
- .then(() => withTarballStream(spec, opts, stream => {
57
- return rimraf(dest)
58
- .then(() => new BB((resolve, reject) => {
59
- const writer = fs.createWriteStream(dest)
60
- stream.on('error', reject)
61
- writer.on('error', reject)
62
- writer.on('close', resolve)
63
- stream.pipe(writer)
57
+ .then(() => withTarballStream(spec, opts, stream => {
58
+ return rimraf(dest)
59
+ .then(() => new BB((resolve, reject) => {
60
+ const writer = fs.createWriteStream(dest)
61
+ stream.on('error', reject)
62
+ writer.on('error', reject)
63
+ writer.on('close', resolve)
64
+ stream.pipe(writer)
65
+ }))
64
66
  }))
65
- }))
66
67
  }