pacote 18.0.4 → 18.0.6
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/{lib/bin.js → bin/index.js} +0 -1
- package/lib/dir.js +10 -13
- package/lib/fetcher.js +38 -55
- package/lib/file.js +9 -12
- package/lib/git.js +49 -59
- package/lib/index.js +5 -5
- package/lib/registry.js +22 -23
- package/lib/remote.js +7 -9
- package/lib/util/cache-dir.js +4 -4
- package/lib/util/protected.js +5 -0
- package/package.json +2 -2
package/lib/dir.js
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
+
const { resolve } = require('node:path')
|
|
2
|
+
const packlist = require('npm-packlist')
|
|
3
|
+
const runScript = require('@npmcli/run-script')
|
|
4
|
+
const tar = require('tar')
|
|
5
|
+
const { Minipass } = require('minipass')
|
|
1
6
|
const Fetcher = require('./fetcher.js')
|
|
2
7
|
const FileFetcher = require('./file.js')
|
|
3
|
-
const
|
|
8
|
+
const _ = require('./util/protected.js')
|
|
4
9
|
const tarCreateOptions = require('./util/tar-create-options.js')
|
|
5
|
-
const packlist = require('npm-packlist')
|
|
6
|
-
const tar = require('tar')
|
|
7
|
-
const _prepareDir = Symbol('_prepareDir')
|
|
8
|
-
const { resolve } = require('path')
|
|
9
|
-
const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
|
|
10
|
-
|
|
11
|
-
const runScript = require('@npmcli/run-script')
|
|
12
10
|
|
|
13
|
-
const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
|
|
14
11
|
class DirFetcher extends Fetcher {
|
|
15
12
|
constructor (spec, opts) {
|
|
16
13
|
super(spec, opts)
|
|
@@ -30,7 +27,7 @@ class DirFetcher extends Fetcher {
|
|
|
30
27
|
return ['directory']
|
|
31
28
|
}
|
|
32
29
|
|
|
33
|
-
|
|
30
|
+
#prepareDir () {
|
|
34
31
|
return this.manifest().then(mani => {
|
|
35
32
|
if (!mani.scripts || !mani.scripts.prepare) {
|
|
36
33
|
return
|
|
@@ -55,7 +52,7 @@ class DirFetcher extends Fetcher {
|
|
|
55
52
|
})
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
[
|
|
55
|
+
[_.tarballFromResolved] () {
|
|
59
56
|
if (!this.tree && !this.Arborist) {
|
|
60
57
|
throw new Error('DirFetcher requires either a tree or an Arborist constructor to pack')
|
|
61
58
|
}
|
|
@@ -68,7 +65,7 @@ class DirFetcher extends Fetcher {
|
|
|
68
65
|
|
|
69
66
|
// run the prepare script, get the list of files, and tar it up
|
|
70
67
|
// pipe to the stream, and proxy errors the chain.
|
|
71
|
-
this
|
|
68
|
+
this.#prepareDir()
|
|
72
69
|
.then(async () => {
|
|
73
70
|
if (!this.tree) {
|
|
74
71
|
const arb = new this.Arborist({ path: this.resolved })
|
|
@@ -87,7 +84,7 @@ class DirFetcher extends Fetcher {
|
|
|
87
84
|
return Promise.resolve(this.package)
|
|
88
85
|
}
|
|
89
86
|
|
|
90
|
-
return this[
|
|
87
|
+
return this[_.readPackageJson](this.resolved)
|
|
91
88
|
.then(mani => this.package = {
|
|
92
89
|
...mani,
|
|
93
90
|
_integrity: this.integrity && String(this.integrity),
|
package/lib/fetcher.js
CHANGED
|
@@ -3,42 +3,27 @@
|
|
|
3
3
|
// It handles the unpacking and retry logic that is shared among
|
|
4
4
|
// all of the other Fetcher types.
|
|
5
5
|
|
|
6
|
+
const { basename, dirname } = require('node:path')
|
|
7
|
+
const { rm, mkdir } = require('node:fs/promises')
|
|
8
|
+
const PackageJson = require('@npmcli/package-json')
|
|
9
|
+
const cacache = require('cacache')
|
|
10
|
+
const fsm = require('fs-minipass')
|
|
11
|
+
const getContents = require('@npmcli/installed-package-contents')
|
|
6
12
|
const npa = require('npm-package-arg')
|
|
13
|
+
const retry = require('promise-retry')
|
|
7
14
|
const ssri = require('ssri')
|
|
8
|
-
const { basename, dirname } = require('path')
|
|
9
15
|
const tar = require('tar')
|
|
16
|
+
const { Minipass } = require('minipass')
|
|
10
17
|
const { log } = require('proc-log')
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const fsm = require('fs-minipass')
|
|
14
|
-
const cacache = require('cacache')
|
|
18
|
+
const _ = require('./util/protected.js')
|
|
19
|
+
const cacheDir = require('./util/cache-dir.js')
|
|
15
20
|
const isPackageBin = require('./util/is-package-bin.js')
|
|
16
21
|
const removeTrailingSlashes = require('./util/trailing-slashes.js')
|
|
17
|
-
const getContents = require('@npmcli/installed-package-contents')
|
|
18
|
-
const PackageJson = require('@npmcli/package-json')
|
|
19
|
-
const { Minipass } = require('minipass')
|
|
20
|
-
const cacheDir = require('./util/cache-dir.js')
|
|
21
22
|
|
|
22
23
|
// Pacote is only concerned with the package.json contents
|
|
23
24
|
const packageJsonPrepare = (p) => PackageJson.prepare(p).then(pkg => pkg.content)
|
|
24
25
|
const packageJsonNormalize = (p) => PackageJson.normalize(p).then(pkg => pkg.content)
|
|
25
26
|
|
|
26
|
-
// Private methods.
|
|
27
|
-
// Child classes should not have to override these.
|
|
28
|
-
// Users should never call them.
|
|
29
|
-
const _extract = Symbol('_extract')
|
|
30
|
-
const _mkdir = Symbol('_mkdir')
|
|
31
|
-
const _empty = Symbol('_empty')
|
|
32
|
-
const _toFile = Symbol('_toFile')
|
|
33
|
-
const _tarxOptions = Symbol('_tarxOptions')
|
|
34
|
-
const _entryMode = Symbol('_entryMode')
|
|
35
|
-
const _istream = Symbol('_istream')
|
|
36
|
-
const _assertType = Symbol('_assertType')
|
|
37
|
-
const _tarballFromCache = Symbol('_tarballFromCache')
|
|
38
|
-
const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
|
|
39
|
-
const _cacheFetches = Symbol.for('pacote.Fetcher._cacheFetches')
|
|
40
|
-
const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
|
|
41
|
-
|
|
42
27
|
class FetcherBase {
|
|
43
28
|
constructor (spec, opts) {
|
|
44
29
|
if (!opts || typeof opts !== 'object') {
|
|
@@ -57,7 +42,7 @@ class FetcherBase {
|
|
|
57
42
|
this.from = this.spec.registry
|
|
58
43
|
? `${this.spec.name}@${this.spec.rawSpec}` : this.spec.saveSpec
|
|
59
44
|
|
|
60
|
-
this
|
|
45
|
+
this.#assertType()
|
|
61
46
|
// clone the opts object so that others aren't upset when we mutate it
|
|
62
47
|
// by adding/modifying the integrity value.
|
|
63
48
|
this.opts = { ...opts }
|
|
@@ -93,11 +78,9 @@ class FetcherBase {
|
|
|
93
78
|
this.before = opts.before
|
|
94
79
|
this.fullMetadata = this.before ? true : !!opts.fullMetadata
|
|
95
80
|
this.fullReadJson = !!opts.fullReadJson
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this[_readPackageJson] = packageJsonNormalize
|
|
100
|
-
}
|
|
81
|
+
this[_.readPackageJson] = this.fullReadJson
|
|
82
|
+
? packageJsonPrepare
|
|
83
|
+
: packageJsonNormalize
|
|
101
84
|
|
|
102
85
|
// rrh is a registry hostname or 'never' or 'always'
|
|
103
86
|
// defaults to registry.npmjs.org
|
|
@@ -188,7 +171,7 @@ class FetcherBase {
|
|
|
188
171
|
// private, should be overridden.
|
|
189
172
|
// Note that they should *not* calculate or check integrity or cache,
|
|
190
173
|
// but *just* return the raw tarball data stream.
|
|
191
|
-
[
|
|
174
|
+
[_.tarballFromResolved] () {
|
|
192
175
|
throw this.notImplementedError
|
|
193
176
|
}
|
|
194
177
|
|
|
@@ -204,17 +187,17 @@ class FetcherBase {
|
|
|
204
187
|
|
|
205
188
|
// private
|
|
206
189
|
// Note: cacache will raise a EINTEGRITY error if the integrity doesn't match
|
|
207
|
-
|
|
190
|
+
#tarballFromCache () {
|
|
208
191
|
return cacache.get.stream.byDigest(this.cache, this.integrity, this.opts)
|
|
209
192
|
}
|
|
210
193
|
|
|
211
|
-
get [
|
|
194
|
+
get [_.cacheFetches] () {
|
|
212
195
|
return true
|
|
213
196
|
}
|
|
214
197
|
|
|
215
|
-
|
|
198
|
+
#istream (stream) {
|
|
216
199
|
// if not caching this, just return it
|
|
217
|
-
if (!this.opts.cache || !this[
|
|
200
|
+
if (!this.opts.cache || !this[_.cacheFetches]) {
|
|
218
201
|
// instead of creating a new integrity stream, we only piggyback on the
|
|
219
202
|
// provided stream's events
|
|
220
203
|
if (stream.hasIntegrityEmitter) {
|
|
@@ -267,7 +250,7 @@ class FetcherBase {
|
|
|
267
250
|
return false
|
|
268
251
|
}
|
|
269
252
|
|
|
270
|
-
|
|
253
|
+
#assertType () {
|
|
271
254
|
if (this.types && !this.types.includes(this.spec.type)) {
|
|
272
255
|
throw new TypeError(`Wrong spec type (${
|
|
273
256
|
this.spec.type
|
|
@@ -306,7 +289,7 @@ class FetcherBase {
|
|
|
306
289
|
!this.preferOnline &&
|
|
307
290
|
this.integrity &&
|
|
308
291
|
this.resolved
|
|
309
|
-
) ? streamHandler(this
|
|
292
|
+
) ? streamHandler(this.#tarballFromCache()).catch(er => {
|
|
310
293
|
if (this.isDataCorruptionError(er)) {
|
|
311
294
|
log.warn('tarball', `cached data for ${
|
|
312
295
|
this.spec
|
|
@@ -329,7 +312,7 @@ class FetcherBase {
|
|
|
329
312
|
}. Extracting by manifest.`)
|
|
330
313
|
}
|
|
331
314
|
return this.resolve().then(() => retry(tryAgain =>
|
|
332
|
-
streamHandler(this
|
|
315
|
+
streamHandler(this.#istream(this[_.tarballFromResolved]()))
|
|
333
316
|
.catch(streamErr => {
|
|
334
317
|
// Most likely data integrity. A cache ENOENT error is unlikely
|
|
335
318
|
// here, since we're definitely not reading from the cache, but it
|
|
@@ -352,24 +335,24 @@ class FetcherBase {
|
|
|
352
335
|
return cacache.rm.content(this.cache, this.integrity, this.opts)
|
|
353
336
|
}
|
|
354
337
|
|
|
355
|
-
|
|
338
|
+
#empty (path) {
|
|
356
339
|
return getContents({ path, depth: 1 }).then(contents => Promise.all(
|
|
357
|
-
contents.map(entry =>
|
|
340
|
+
contents.map(entry => rm(entry, { recursive: true, force: true }))))
|
|
358
341
|
}
|
|
359
342
|
|
|
360
|
-
async
|
|
361
|
-
await this
|
|
362
|
-
return await
|
|
343
|
+
async #mkdir (dest) {
|
|
344
|
+
await this.#empty(dest)
|
|
345
|
+
return await mkdir(dest, { recursive: true })
|
|
363
346
|
}
|
|
364
347
|
|
|
365
348
|
// extraction is always the same. the only difference is where
|
|
366
349
|
// the tarball comes from.
|
|
367
350
|
async extract (dest) {
|
|
368
|
-
await this
|
|
369
|
-
return this.tarballStream((tarball) => this
|
|
351
|
+
await this.#mkdir(dest)
|
|
352
|
+
return this.tarballStream((tarball) => this.#extract(dest, tarball))
|
|
370
353
|
}
|
|
371
354
|
|
|
372
|
-
|
|
355
|
+
#toFile (dest) {
|
|
373
356
|
return this.tarballStream(str => new Promise((res, rej) => {
|
|
374
357
|
const writer = new fsm.WriteStream(dest)
|
|
375
358
|
str.on('error', er => writer.emit('error', er))
|
|
@@ -383,15 +366,15 @@ class FetcherBase {
|
|
|
383
366
|
}))
|
|
384
367
|
}
|
|
385
368
|
|
|
386
|
-
// don't use this
|
|
369
|
+
// don't use this.#mkdir because we don't want to rimraf anything
|
|
387
370
|
async tarballFile (dest) {
|
|
388
371
|
const dir = dirname(dest)
|
|
389
|
-
await
|
|
390
|
-
return this
|
|
372
|
+
await mkdir(dir, { recursive: true })
|
|
373
|
+
return this.#toFile(dest)
|
|
391
374
|
}
|
|
392
375
|
|
|
393
|
-
|
|
394
|
-
const extractor = tar.x(this
|
|
376
|
+
#extract (dest, tarball) {
|
|
377
|
+
const extractor = tar.x(this.#tarxOptions({ cwd: dest }))
|
|
395
378
|
const p = new Promise((resolve, reject) => {
|
|
396
379
|
extractor.on('end', () => {
|
|
397
380
|
resolve({
|
|
@@ -416,7 +399,7 @@ class FetcherBase {
|
|
|
416
399
|
|
|
417
400
|
// always ensure that entries are at least as permissive as our configured
|
|
418
401
|
// dmode/fmode, but never more permissive than the umask allows.
|
|
419
|
-
|
|
402
|
+
#entryMode (path, mode, type) {
|
|
420
403
|
const m = /Directory|GNUDumpDir/.test(type) ? this.dmode
|
|
421
404
|
: /File$/.test(type) ? this.fmode
|
|
422
405
|
: /* istanbul ignore next - should never happen in a pkg */ 0
|
|
@@ -427,7 +410,7 @@ class FetcherBase {
|
|
|
427
410
|
return ((mode | m) & ~this.umask) | exe | 0o600
|
|
428
411
|
}
|
|
429
412
|
|
|
430
|
-
|
|
413
|
+
#tarxOptions ({ cwd }) {
|
|
431
414
|
const sawIgnores = new Set()
|
|
432
415
|
return {
|
|
433
416
|
cwd,
|
|
@@ -437,7 +420,7 @@ class FetcherBase {
|
|
|
437
420
|
if (/Link$/.test(entry.type)) {
|
|
438
421
|
return false
|
|
439
422
|
}
|
|
440
|
-
entry.mode = this
|
|
423
|
+
entry.mode = this.#entryMode(entry.path, entry.mode, entry.type)
|
|
441
424
|
// this replicates the npm pack behavior where .gitignore files
|
|
442
425
|
// are treated like .npmignore files, but only if a .npmignore
|
|
443
426
|
// file is not present.
|
package/lib/file.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { resolve } = require('node:path')
|
|
2
|
+
const { stat, chmod } = require('node:fs/promises')
|
|
2
3
|
const cacache = require('cacache')
|
|
3
|
-
const
|
|
4
|
-
const { stat, chmod } = require('fs/promises')
|
|
4
|
+
const fsm = require('fs-minipass')
|
|
5
5
|
const Fetcher = require('./fetcher.js')
|
|
6
|
-
|
|
7
|
-
const _exeBins = Symbol('_exeBins')
|
|
8
|
-
const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
|
|
9
|
-
const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
|
|
6
|
+
const _ = require('./util/protected.js')
|
|
10
7
|
|
|
11
8
|
class FileFetcher extends Fetcher {
|
|
12
9
|
constructor (spec, opts) {
|
|
@@ -27,7 +24,7 @@ class FileFetcher extends Fetcher {
|
|
|
27
24
|
// have to unpack the tarball for this.
|
|
28
25
|
return cacache.tmp.withTmp(this.cache, this.opts, dir =>
|
|
29
26
|
this.extract(dir)
|
|
30
|
-
.then(() => this[
|
|
27
|
+
.then(() => this[_.readPackageJson](dir))
|
|
31
28
|
.then(mani => this.package = {
|
|
32
29
|
...mani,
|
|
33
30
|
_integrity: this.integrity && String(this.integrity),
|
|
@@ -36,7 +33,7 @@ class FileFetcher extends Fetcher {
|
|
|
36
33
|
}))
|
|
37
34
|
}
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
#exeBins (pkg, dest) {
|
|
40
37
|
if (!pkg.bin) {
|
|
41
38
|
return Promise.resolve()
|
|
42
39
|
}
|
|
@@ -65,11 +62,11 @@ class FileFetcher extends Fetcher {
|
|
|
65
62
|
// but if not, read the unpacked manifest and chmod properly.
|
|
66
63
|
return super.extract(dest)
|
|
67
64
|
.then(result => this.package ? result
|
|
68
|
-
: this[
|
|
69
|
-
this
|
|
65
|
+
: this[_.readPackageJson](dest).then(pkg =>
|
|
66
|
+
this.#exeBins(pkg, dest)).then(() => result))
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
[
|
|
69
|
+
[_.tarballFromResolved] () {
|
|
73
70
|
// create a read stream and return it
|
|
74
71
|
return new fsm.ReadStream(this.resolved)
|
|
75
72
|
}
|
package/lib/git.js
CHANGED
|
@@ -1,28 +1,18 @@
|
|
|
1
|
-
const
|
|
2
|
-
const FileFetcher = require('./file.js')
|
|
3
|
-
const RemoteFetcher = require('./remote.js')
|
|
4
|
-
const DirFetcher = require('./dir.js')
|
|
5
|
-
const hashre = /^[a-f0-9]{40}$/
|
|
1
|
+
const cacache = require('cacache')
|
|
6
2
|
const git = require('@npmcli/git')
|
|
7
|
-
const pickManifest = require('npm-pick-manifest')
|
|
8
3
|
const npa = require('npm-package-arg')
|
|
4
|
+
const pickManifest = require('npm-pick-manifest')
|
|
9
5
|
const { Minipass } = require('minipass')
|
|
10
|
-
const cacache = require('cacache')
|
|
11
6
|
const { log } = require('proc-log')
|
|
7
|
+
const DirFetcher = require('./dir.js')
|
|
8
|
+
const Fetcher = require('./fetcher.js')
|
|
9
|
+
const FileFetcher = require('./file.js')
|
|
10
|
+
const RemoteFetcher = require('./remote.js')
|
|
11
|
+
const _ = require('./util/protected.js')
|
|
12
|
+
const addGitSha = require('./util/add-git-sha.js')
|
|
12
13
|
const npm = require('./util/npm.js')
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
-
const _resolvedFromHosted = Symbol('_resolvedFromHosted')
|
|
16
|
-
const _resolvedFromClone = Symbol('_resolvedFromClone')
|
|
17
|
-
const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
|
|
18
|
-
const _addGitSha = Symbol('_addGitSha')
|
|
19
|
-
const addGitSha = require('./util/add-git-sha.js')
|
|
20
|
-
const _clone = Symbol('_clone')
|
|
21
|
-
const _cloneHosted = Symbol('_cloneHosted')
|
|
22
|
-
const _cloneRepo = Symbol('_cloneRepo')
|
|
23
|
-
const _setResolvedWithSha = Symbol('_setResolvedWithSha')
|
|
24
|
-
const _prepareDir = Symbol('_prepareDir')
|
|
25
|
-
const _readPackageJson = Symbol.for('package.Fetcher._readPackageJson')
|
|
15
|
+
const hashre = /^[a-f0-9]{40}$/
|
|
26
16
|
|
|
27
17
|
// get the repository url.
|
|
28
18
|
// prefer https if there's auth, since ssh will drop that.
|
|
@@ -84,8 +74,9 @@ class GitFetcher extends Fetcher {
|
|
|
84
74
|
// fetch the git repo and then look at the current hash
|
|
85
75
|
const h = this.spec.hosted
|
|
86
76
|
// try to use ssh, fall back to git.
|
|
87
|
-
return h
|
|
88
|
-
|
|
77
|
+
return h
|
|
78
|
+
? this.#resolvedFromHosted(h)
|
|
79
|
+
: this.#resolvedFromRepo(this.spec.fetchSpec)
|
|
89
80
|
}
|
|
90
81
|
|
|
91
82
|
// first try https, since that's faster and passphrase-less for
|
|
@@ -93,23 +84,22 @@ class GitFetcher extends Fetcher {
|
|
|
93
84
|
// Fall back to SSH to support private repos
|
|
94
85
|
// NB: we always store the https url in resolved field if auth
|
|
95
86
|
// is present, otherwise ssh if the hosted type provides it
|
|
96
|
-
|
|
97
|
-
return this
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
})
|
|
87
|
+
#resolvedFromHosted (hosted) {
|
|
88
|
+
return this.#resolvedFromRepo(hosted.https && hosted.https()).catch(er => {
|
|
89
|
+
// Throw early since we know pathspec errors will fail again if retried
|
|
90
|
+
if (er instanceof git.errors.GitPathspecError) {
|
|
91
|
+
throw er
|
|
92
|
+
}
|
|
93
|
+
const ssh = hosted.sshurl && hosted.sshurl()
|
|
94
|
+
// no fallthrough if we can't fall through or have https auth
|
|
95
|
+
if (!ssh || hosted.auth) {
|
|
96
|
+
throw er
|
|
97
|
+
}
|
|
98
|
+
return this.#resolvedFromRepo(ssh)
|
|
99
|
+
})
|
|
110
100
|
}
|
|
111
101
|
|
|
112
|
-
|
|
102
|
+
#resolvedFromRepo (gitRemote) {
|
|
113
103
|
// XXX make this a custom error class
|
|
114
104
|
if (!gitRemote) {
|
|
115
105
|
return Promise.reject(new Error(`No git url for ${this.spec}`))
|
|
@@ -130,17 +120,17 @@ class GitFetcher extends Fetcher {
|
|
|
130
120
|
// the committish provided isn't in the rev list
|
|
131
121
|
// things like HEAD~3 or @yesterday can land here.
|
|
132
122
|
if (!revDoc || !revDoc.sha) {
|
|
133
|
-
return this
|
|
123
|
+
return this.#resolvedFromClone()
|
|
134
124
|
}
|
|
135
125
|
|
|
136
126
|
this.resolvedRef = revDoc
|
|
137
127
|
this.resolvedSha = revDoc.sha
|
|
138
|
-
this
|
|
128
|
+
this.#addGitSha(revDoc.sha)
|
|
139
129
|
return this.resolved
|
|
140
130
|
})
|
|
141
131
|
}
|
|
142
132
|
|
|
143
|
-
|
|
133
|
+
#setResolvedWithSha (withSha) {
|
|
144
134
|
// we haven't cloned, so a tgz download is still faster
|
|
145
135
|
// of course, if it's not a known host, we can't do that.
|
|
146
136
|
this.resolved = !this.spec.hosted ? withSha
|
|
@@ -149,18 +139,18 @@ class GitFetcher extends Fetcher {
|
|
|
149
139
|
|
|
150
140
|
// when we get the git sha, we affix it to our spec to build up
|
|
151
141
|
// either a git url with a hash, or a tarball download URL
|
|
152
|
-
|
|
153
|
-
this
|
|
142
|
+
#addGitSha (sha) {
|
|
143
|
+
this.#setResolvedWithSha(addGitSha(this.spec, sha))
|
|
154
144
|
}
|
|
155
145
|
|
|
156
|
-
|
|
146
|
+
#resolvedFromClone () {
|
|
157
147
|
// do a full or shallow clone, then look at the HEAD
|
|
158
148
|
// kind of wasteful, but no other option, really
|
|
159
|
-
return this
|
|
149
|
+
return this.#clone(() => this.resolved)
|
|
160
150
|
}
|
|
161
151
|
|
|
162
|
-
|
|
163
|
-
return this[
|
|
152
|
+
#prepareDir (dir) {
|
|
153
|
+
return this[_.readPackageJson](dir).then(mani => {
|
|
164
154
|
// no need if we aren't going to do any preparation.
|
|
165
155
|
const scripts = mani.scripts
|
|
166
156
|
if (!mani.workspaces && (!scripts || !(
|
|
@@ -200,13 +190,13 @@ class GitFetcher extends Fetcher {
|
|
|
200
190
|
})
|
|
201
191
|
}
|
|
202
192
|
|
|
203
|
-
[
|
|
193
|
+
[_.tarballFromResolved] () {
|
|
204
194
|
const stream = new Minipass()
|
|
205
195
|
stream.resolved = this.resolved
|
|
206
196
|
stream.from = this.from
|
|
207
197
|
|
|
208
198
|
// check it out and then shell out to the DirFetcher tarball packer
|
|
209
|
-
this
|
|
199
|
+
this.#clone(dir => this.#prepareDir(dir)
|
|
210
200
|
.then(() => new Promise((res, rej) => {
|
|
211
201
|
if (!this.Arborist) {
|
|
212
202
|
throw new Error('GitFetcher requires an Arborist constructor to pack a tarball')
|
|
@@ -217,7 +207,7 @@ class GitFetcher extends Fetcher {
|
|
|
217
207
|
resolved: null,
|
|
218
208
|
integrity: null,
|
|
219
209
|
})
|
|
220
|
-
const dirStream = df[
|
|
210
|
+
const dirStream = df[_.tarballFromResolved]()
|
|
221
211
|
dirStream.on('error', rej)
|
|
222
212
|
dirStream.on('end', res)
|
|
223
213
|
dirStream.pipe(stream)
|
|
@@ -235,7 +225,7 @@ class GitFetcher extends Fetcher {
|
|
|
235
225
|
// TODO: after cloning, create a tarball of the folder, and add to the cache
|
|
236
226
|
// with cacache.put.stream(), using a key that's deterministic based on the
|
|
237
227
|
// spec and repo, so that we don't ever clone the same thing multiple times.
|
|
238
|
-
|
|
228
|
+
#clone (handler, tarballOk = true) {
|
|
239
229
|
const o = { tmpPrefix: 'git-clone' }
|
|
240
230
|
const ref = this.resolvedSha || this.spec.gitCommittish
|
|
241
231
|
const h = this.spec.hosted
|
|
@@ -258,7 +248,7 @@ class GitFetcher extends Fetcher {
|
|
|
258
248
|
}).extract(tmp).then(() => handler(tmp), er => {
|
|
259
249
|
// fall back to ssh download if tarball fails
|
|
260
250
|
if (er.constructor.name.match(/^Http/)) {
|
|
261
|
-
return this
|
|
251
|
+
return this.#clone(handler, false)
|
|
262
252
|
} else {
|
|
263
253
|
throw er
|
|
264
254
|
}
|
|
@@ -266,12 +256,12 @@ class GitFetcher extends Fetcher {
|
|
|
266
256
|
}
|
|
267
257
|
|
|
268
258
|
const sha = await (
|
|
269
|
-
h ? this
|
|
270
|
-
: this
|
|
259
|
+
h ? this.#cloneHosted(ref, tmp)
|
|
260
|
+
: this.#cloneRepo(this.spec.fetchSpec, ref, tmp)
|
|
271
261
|
)
|
|
272
262
|
this.resolvedSha = sha
|
|
273
263
|
if (!this.resolved) {
|
|
274
|
-
await this
|
|
264
|
+
await this.#addGitSha(sha)
|
|
275
265
|
}
|
|
276
266
|
return handler(tmp)
|
|
277
267
|
})
|
|
@@ -282,9 +272,9 @@ class GitFetcher extends Fetcher {
|
|
|
282
272
|
// Fall back to SSH to support private repos
|
|
283
273
|
// NB: we always store the https url in resolved field if auth
|
|
284
274
|
// is present, otherwise ssh if the hosted type provides it
|
|
285
|
-
|
|
275
|
+
#cloneHosted (ref, tmp) {
|
|
286
276
|
const hosted = this.spec.hosted
|
|
287
|
-
return this
|
|
277
|
+
return this.#cloneRepo(hosted.https({ noCommittish: true }), ref, tmp)
|
|
288
278
|
.catch(er => {
|
|
289
279
|
// Throw early since we know pathspec errors will fail again if retried
|
|
290
280
|
if (er instanceof git.errors.GitPathspecError) {
|
|
@@ -295,11 +285,11 @@ class GitFetcher extends Fetcher {
|
|
|
295
285
|
if (!ssh || hosted.auth) {
|
|
296
286
|
throw er
|
|
297
287
|
}
|
|
298
|
-
return this
|
|
288
|
+
return this.#cloneRepo(ssh, ref, tmp)
|
|
299
289
|
})
|
|
300
290
|
}
|
|
301
291
|
|
|
302
|
-
|
|
292
|
+
#cloneRepo (repo, ref, tmp) {
|
|
303
293
|
const { opts, spec } = this
|
|
304
294
|
return git.clone(repo, ref, tmp, { ...opts, spec })
|
|
305
295
|
}
|
|
@@ -311,8 +301,8 @@ class GitFetcher extends Fetcher {
|
|
|
311
301
|
|
|
312
302
|
return this.spec.hosted && this.resolved
|
|
313
303
|
? FileFetcher.prototype.manifest.apply(this)
|
|
314
|
-
: this
|
|
315
|
-
this[
|
|
304
|
+
: this.#clone(dir =>
|
|
305
|
+
this[_.readPackageJson](dir)
|
|
316
306
|
.then(mani => this.package = {
|
|
317
307
|
...mani,
|
|
318
308
|
_resolved: this.resolved,
|
package/lib/index.js
CHANGED
|
@@ -5,6 +5,10 @@ const FileFetcher = require('./file.js')
|
|
|
5
5
|
const DirFetcher = require('./dir.js')
|
|
6
6
|
const RemoteFetcher = require('./remote.js')
|
|
7
7
|
|
|
8
|
+
const tarball = (spec, opts) => get(spec, opts).tarball()
|
|
9
|
+
tarball.stream = (spec, handler, opts) => get(spec, opts).tarballStream(handler)
|
|
10
|
+
tarball.file = (spec, dest, opts) => get(spec, opts).tarballFile(dest)
|
|
11
|
+
|
|
8
12
|
module.exports = {
|
|
9
13
|
GitFetcher,
|
|
10
14
|
RegistryFetcher,
|
|
@@ -14,10 +18,6 @@ module.exports = {
|
|
|
14
18
|
resolve: (spec, opts) => get(spec, opts).resolve(),
|
|
15
19
|
extract: (spec, dest, opts) => get(spec, opts).extract(dest),
|
|
16
20
|
manifest: (spec, opts) => get(spec, opts).manifest(),
|
|
17
|
-
tarball: (spec, opts) => get(spec, opts).tarball(),
|
|
18
21
|
packument: (spec, opts) => get(spec, opts).packument(),
|
|
22
|
+
tarball,
|
|
19
23
|
}
|
|
20
|
-
module.exports.tarball.stream = (spec, handler, opts) =>
|
|
21
|
-
get(spec, opts).tarballStream(handler)
|
|
22
|
-
module.exports.tarball.file = (spec, dest, opts) =>
|
|
23
|
-
get(spec, opts).tarballFile(dest)
|
package/lib/registry.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
const
|
|
2
|
-
const RemoteFetcher = require('./remote.js')
|
|
3
|
-
const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
|
|
4
|
-
const pacoteVersion = require('../package.json').version
|
|
5
|
-
const removeTrailingSlashes = require('./util/trailing-slashes.js')
|
|
1
|
+
const crypto = require('node:crypto')
|
|
6
2
|
const PackageJson = require('@npmcli/package-json')
|
|
7
3
|
const pickManifest = require('npm-pick-manifest')
|
|
8
4
|
const ssri = require('ssri')
|
|
9
|
-
const crypto = require('crypto')
|
|
10
5
|
const npa = require('npm-package-arg')
|
|
11
6
|
const sigstore = require('sigstore')
|
|
7
|
+
const fetch = require('npm-registry-fetch')
|
|
8
|
+
const Fetcher = require('./fetcher.js')
|
|
9
|
+
const RemoteFetcher = require('./remote.js')
|
|
10
|
+
const pacoteVersion = require('../package.json').version
|
|
11
|
+
const removeTrailingSlashes = require('./util/trailing-slashes.js')
|
|
12
|
+
const _ = require('./util/protected.js')
|
|
12
13
|
|
|
13
14
|
// Corgis are cute. 🐕🐶
|
|
14
15
|
const corgiDoc = 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*'
|
|
@@ -18,10 +19,8 @@ const fullDoc = 'application/json'
|
|
|
18
19
|
// cutoff date.
|
|
19
20
|
const MISSING_TIME_CUTOFF = '2015-01-01T00:00:00.000Z'
|
|
20
21
|
|
|
21
|
-
const fetch = require('npm-registry-fetch')
|
|
22
|
-
|
|
23
|
-
const _headers = Symbol('_headers')
|
|
24
22
|
class RegistryFetcher extends Fetcher {
|
|
23
|
+
#cacheKey
|
|
25
24
|
constructor (spec, opts) {
|
|
26
25
|
super(spec, opts)
|
|
27
26
|
|
|
@@ -34,8 +33,8 @@ class RegistryFetcher extends Fetcher {
|
|
|
34
33
|
this.packumentCache = this.opts.packumentCache || null
|
|
35
34
|
|
|
36
35
|
this.registry = fetch.pickRegistry(spec, opts)
|
|
37
|
-
this.packumentUrl = removeTrailingSlashes(this.registry)
|
|
38
|
-
|
|
36
|
+
this.packumentUrl = `${removeTrailingSlashes(this.registry)}/${this.spec.escapedName}`
|
|
37
|
+
this.#cacheKey = `${this.fullMetadata ? 'full' : 'corgi'}:${this.packumentUrl}`
|
|
39
38
|
|
|
40
39
|
const parsed = new URL(this.registry)
|
|
41
40
|
const regKey = `//${parsed.host}${parsed.pathname}`
|
|
@@ -63,7 +62,7 @@ class RegistryFetcher extends Fetcher {
|
|
|
63
62
|
return this.resolved
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
|
|
65
|
+
#headers () {
|
|
67
66
|
return {
|
|
68
67
|
// npm will override UA, but ensure that we always send *something*
|
|
69
68
|
'user-agent': this.opts.userAgent ||
|
|
@@ -80,8 +79,8 @@ class RegistryFetcher extends Fetcher {
|
|
|
80
79
|
// note this might be either an in-flight promise for a request,
|
|
81
80
|
// or the actual packument, but we never want to make more than
|
|
82
81
|
// one request at a time for the same thing regardless.
|
|
83
|
-
if (this.packumentCache
|
|
84
|
-
return this.packumentCache.get(this
|
|
82
|
+
if (this.packumentCache?.has(this.#cacheKey)) {
|
|
83
|
+
return this.packumentCache.get(this.#cacheKey)
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
// npm-registry-fetch the packument
|
|
@@ -90,21 +89,21 @@ class RegistryFetcher extends Fetcher {
|
|
|
90
89
|
try {
|
|
91
90
|
const res = await fetch(this.packumentUrl, {
|
|
92
91
|
...this.opts,
|
|
93
|
-
headers: this
|
|
92
|
+
headers: this.#headers(),
|
|
94
93
|
spec: this.spec,
|
|
94
|
+
|
|
95
95
|
// never check integrity for packuments themselves
|
|
96
96
|
integrity: null,
|
|
97
97
|
})
|
|
98
98
|
const packument = await res.json()
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
|
|
99
|
+
const contentLength = res.headers.get('content-length')
|
|
100
|
+
if (contentLength) {
|
|
101
|
+
packument._contentLength = Number(contentLength)
|
|
102
102
|
}
|
|
103
|
+
this.packumentCache?.set(this.#cacheKey, packument)
|
|
103
104
|
return packument
|
|
104
105
|
} catch (err) {
|
|
105
|
-
|
|
106
|
-
this.packumentCache.delete(this.packumentUrl)
|
|
107
|
-
}
|
|
106
|
+
this.packumentCache?.delete(this.#cacheKey)
|
|
108
107
|
if (err.code !== 'E404' || this.fullMetadata) {
|
|
109
108
|
throw err
|
|
110
109
|
}
|
|
@@ -350,13 +349,13 @@ class RegistryFetcher extends Fetcher {
|
|
|
350
349
|
return this.package
|
|
351
350
|
}
|
|
352
351
|
|
|
353
|
-
[
|
|
352
|
+
[_.tarballFromResolved] () {
|
|
354
353
|
// we use a RemoteFetcher to get the actual tarball stream
|
|
355
354
|
return new RemoteFetcher(this.resolved, {
|
|
356
355
|
...this.opts,
|
|
357
356
|
resolved: this.resolved,
|
|
358
357
|
pkgid: `registry:${this.spec.name}@${this.resolved}`,
|
|
359
|
-
})[
|
|
358
|
+
})[_.tarballFromResolved]()
|
|
360
359
|
}
|
|
361
360
|
|
|
362
361
|
get types () {
|
package/lib/remote.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
+
const fetch = require('npm-registry-fetch')
|
|
2
|
+
const { Minipass } = require('minipass')
|
|
1
3
|
const Fetcher = require('./fetcher.js')
|
|
2
4
|
const FileFetcher = require('./file.js')
|
|
3
|
-
const
|
|
5
|
+
const _ = require('./util/protected.js')
|
|
4
6
|
const pacoteVersion = require('../package.json').version
|
|
5
|
-
const fetch = require('npm-registry-fetch')
|
|
6
|
-
const { Minipass } = require('minipass')
|
|
7
7
|
|
|
8
|
-
const _cacheFetches = Symbol.for('pacote.Fetcher._cacheFetches')
|
|
9
|
-
const _headers = Symbol('_headers')
|
|
10
8
|
class RemoteFetcher extends Fetcher {
|
|
11
9
|
constructor (spec, opts) {
|
|
12
10
|
super(spec, opts)
|
|
@@ -25,17 +23,17 @@ class RemoteFetcher extends Fetcher {
|
|
|
25
23
|
|
|
26
24
|
// Don't need to cache tarball fetches in pacote, because make-fetch-happen
|
|
27
25
|
// will write into cacache anyway.
|
|
28
|
-
get [
|
|
26
|
+
get [_.cacheFetches] () {
|
|
29
27
|
return false
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
[
|
|
30
|
+
[_.tarballFromResolved] () {
|
|
33
31
|
const stream = new Minipass()
|
|
34
32
|
stream.hasIntegrityEmitter = true
|
|
35
33
|
|
|
36
34
|
const fetchOpts = {
|
|
37
35
|
...this.opts,
|
|
38
|
-
headers: this
|
|
36
|
+
headers: this.#headers(),
|
|
39
37
|
spec: this.spec,
|
|
40
38
|
integrity: this.integrity,
|
|
41
39
|
algorithms: [this.pickIntegrityAlgorithm()],
|
|
@@ -59,7 +57,7 @@ class RemoteFetcher extends Fetcher {
|
|
|
59
57
|
return stream
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
#headers () {
|
|
63
61
|
return {
|
|
64
62
|
// npm will override this, but ensure that we always send *something*
|
|
65
63
|
'user-agent': this.opts.userAgent ||
|
package/lib/util/cache-dir.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const
|
|
2
|
-
const {
|
|
1
|
+
const { resolve } = require('node:path')
|
|
2
|
+
const { tmpdir, homedir } = require('node:os')
|
|
3
3
|
|
|
4
4
|
module.exports = (fakePlatform = false) => {
|
|
5
|
-
const temp =
|
|
5
|
+
const temp = tmpdir()
|
|
6
6
|
const uidOrPid = process.getuid ? process.getuid() : process.pid
|
|
7
|
-
const home =
|
|
7
|
+
const home = homedir() || resolve(temp, 'npm-' + uidOrPid)
|
|
8
8
|
const platform = fakePlatform || process.platform
|
|
9
9
|
const cacheExtra = platform === 'win32' ? 'npm-cache' : '.npm'
|
|
10
10
|
const cacheRoot = (platform === 'win32' && process.env.LOCALAPPDATA) || home
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pacote",
|
|
3
|
-
"version": "18.0.
|
|
3
|
+
"version": "18.0.6",
|
|
4
4
|
"description": "JavaScript package downloader",
|
|
5
5
|
"author": "GitHub Inc.",
|
|
6
6
|
"bin": {
|
|
7
|
-
"pacote": "
|
|
7
|
+
"pacote": "bin/index.js"
|
|
8
8
|
},
|
|
9
9
|
"license": "ISC",
|
|
10
10
|
"main": "lib/index.js",
|