Skip to content

Commit 347c563

Browse files
committed
Cache manifest as fetcher.package
This allows greater efficiency, and will make it possible to set the mode of package bins so that they're always executable.
1 parent 8d38b28 commit 347c563

File tree

10 files changed

+80
-20
lines changed

10 files changed

+80
-20
lines changed

lib/dir.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ class DirFetcher extends Fetcher {
2121
return ['directory']
2222
}
2323

24-
[_prepareDir] (dir) {
25-
return readPackageJson(dir + '/package.json')
26-
.then(mani => {
24+
[_prepareDir] () {
25+
return this.manifest().then(mani => {
2726
if (!mani.scripts || !mani.scripts.prepare)
2827
return
2928

@@ -33,7 +32,7 @@ class DirFetcher extends Fetcher {
3332
return npm(
3433
this.npmBin,
3534
[].concat(this.npmRunCmd).concat('prepare').concat(this.npmCliConfig),
36-
dir,
35+
this.resolved,
3736
'directory preparation failed'
3837
)
3938
})
@@ -46,7 +45,7 @@ class DirFetcher extends Fetcher {
4645

4746
// run the prepare script, get the list of files, and tar it up
4847
// pipe to the stream, and proxy errors the chain.
49-
this[_prepareDir](this.resolved)
48+
this[_prepareDir]()
5049
.then(() => packlist({ path: this.resolved }))
5150
.then(files => tar.c({
5251
cwd: this.resolved,
@@ -63,12 +62,15 @@ class DirFetcher extends Fetcher {
6362
}
6463

6564
manifest () {
65+
if (this.package)
66+
return Promise.resolve(this.package)
67+
6668
return readPackageJson(this.resolved + '/package.json')
67-
.then(mani => ({
69+
.then(mani => this.package = {
6870
...mani,
6971
_integrity: String(this.integrity),
7072
_resolved: this.resolved,
71-
}))
73+
})
7274
}
7375

7476
packument () {

lib/fetcher.js

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class FetcherBase {
4949
this.cache = opts.cache || cacheDir()
5050
this.resolved = opts.resolved || null
5151
this.integrity = opts.integrity || null
52+
this.package = null
5253
this.type = this.constructor.name
5354
this.fmode = opts.fmode || 0o666
5455
this.dmode = opts.dmode || 0o777

lib/file.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,18 @@ class FileFetcher extends Fetcher {
1717
}
1818

1919
manifest () {
20+
if (this.package)
21+
return Promise.resolve(this.package)
22+
2023
// have to unpack the tarball for this.
2124
return cacache.tmp.withTmp(this.cache, this.opts, dir =>
2225
this.extract(dir)
2326
.then(() => readPackageJson(dir + '/package.json'))
24-
.then(mani => ({
27+
.then(mani => this.package = {
2528
...mani,
2629
_integrity: String(this.integrity),
2730
_resolved: this.resolved,
28-
})))
31+
}))
2932
}
3033

3134
[_tarballFromResolved] () {

lib/git.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,18 @@ class GitFetcher extends Fetcher {
203203
}
204204

205205
manifest () {
206+
if (this.package)
207+
return Promise.resolve(this.package)
208+
206209
return this.spec.hosted && this.resolved
207210
? FileFetcher.prototype.manifest.apply(this)
208211
: this[_clone](dir =>
209212
readPackageJson(dir + '/package.json')
210-
.then(mani => ({
213+
.then(mani => this.package = {
211214
...mani,
212215
_integrity: String(this.integrity),
213216
_resolved: this.resolved,
214-
})))
217+
}))
215218
}
216219

217220
packument () {

lib/registry.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ class RegistryFetcher extends Fetcher {
9292
}
9393

9494
manifest () {
95+
if (this.package)
96+
return Promise.resolve(this.package)
97+
9598
return this.packument()
9699
.then(packument => pickManifest(packument, this.spec.fetchSpec, {
97100
...this.opts,
@@ -110,20 +113,18 @@ class RegistryFetcher extends Fetcher {
110113
if (this.integrity)
111114
mani._integrity = String(this.integrity)
112115
}
113-
return mani
116+
return this.package = mani
114117
})
115118
}
116119

117120
[_tarballFromResolved] () {
118121
// we use a RemoteFetcher to get the actual tarball stream
119-
const stream = new Minipass()
120-
new RemoteFetcher(this.resolved, {
122+
return new RemoteFetcher(this.resolved, {
121123
...this.opts,
122124
integrity: this.integrity,
123125
resolved: this.resolved,
124126
pkgid: `registry:${this.spec.name}@${this.resolved}`,
125-
})[_tarballFromResolved]().pipe(stream)
126-
return stream
127+
})[_tarballFromResolved]()
127128
}
128129

129130
get types () {

tap-snapshots/test-dir.js-TAP.test.js

+39
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,45 @@ Object {
126126
}
127127
`
128128

129+
exports[`test/dir.js TAP basic > saved package.json 1`] = `
130+
Object {
131+
132+
"_integrity": "null",
133+
"_resolved": "\${CWD}/test/fixtures/abbrev",
134+
"author": Object {
135+
"email": "[email protected]",
136+
"name": "Isaac Z. Schlueter",
137+
},
138+
"bugs": Object {
139+
"url": "https://github.com/isaacs/abbrev-js/issues",
140+
},
141+
"description": "Like ruby's abbrev module, but in js",
142+
"devDependencies": Object {
143+
"tap": "^10.1",
144+
},
145+
"files": Array [
146+
"abbrev.js",
147+
],
148+
"homepage": "https://github.com/isaacs/abbrev-js#readme",
149+
"license": "ISC",
150+
"main": "abbrev.js",
151+
"name": "abbrev",
152+
"readme": "# abbrev-js\\n\\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\\n\\nUsage:\\n\\n var abbrev = require(\\"abbrev\\");\\n abbrev(\\"foo\\", \\"fool\\", \\"folding\\", \\"flop\\");\\n \\n // returns:\\n { fl: 'flop'\\n , flo: 'flop'\\n , flop: 'flop'\\n , fol: 'folding'\\n , fold: 'folding'\\n , foldi: 'folding'\\n , foldin: 'folding'\\n , folding: 'folding'\\n , foo: 'foo'\\n , fool: 'fool'\\n }\\n\\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\\n",
153+
"readmeFilename": "README.md",
154+
"repository": Object {
155+
"type": "git",
156+
"url": "git+ssh://[email protected]/isaacs/abbrev-js.git",
157+
},
158+
"scripts": Object {
159+
"postpublish": "git push origin --all; git push origin --tags",
160+
"postversion": "npm publish",
161+
"preversion": "npm test",
162+
"test": "tap test.js --100",
163+
},
164+
"version": "1.1.1",
165+
}
166+
`
167+
129168
exports[`test/dir.js TAP with prepare script > extract 1`] = `
130169
Object {
131170
"integrity": "sha512-HTzPAt8wmXNchUdisnGDSCuUgrFee5v8F6GsLc5mQd29VXiNzv4PGz71jjLSIF1wWQSB+UjLTmSJSGznF/s/Lw==",

test/dir.js

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ t.test('basic', t => {
2323
const pj = me + '/abbrev/package.json'
2424
return t.resolveMatchSnapshot(f.extract(me + '/abbrev'), 'extract')
2525
.then(() => t.matchSnapshot(require(pj), 'package.json extracted'))
26+
.then(() => t.matchSnapshot(f.package, 'saved package.json'))
27+
.then(() => f.manifest().then(mani => t.equal(mani, f.package)))
2628
})
2729

2830
const prepare = resolve(__dirname, 'fixtures/prepare-script')

test/file.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ t.teardown(() => rimraf.sync(me))
1414
const abbrev = resolve(__dirname, 'fixtures/abbrev-1.1.1.tgz')
1515
const abbrevspec = `file:${relative(process.cwd(), abbrev)}`
1616

17-
t.test('basic', t => {
17+
t.test('basic', async t => {
1818
const f = new FileFetcher(abbrevspec, {})
1919
t.same(f.types, ['file'])
20-
t.resolveMatchSnapshot(f.packument(), 'packument')
21-
t.resolveMatchSnapshot(f.manifest(), 'manifest')
20+
const fm = await f.manifest()
21+
t.matchSnapshot(fm, 'manifest')
22+
t.equal(fm, f.package)
23+
t.equal(await f.manifest(), fm, 'cached manifest')
24+
t.matchSnapshot(await f.packument(), 'packument')
2225
const pj = me + '/extract/package.json'
2326
return t.resolveMatchSnapshot(f.extract(me + '/extract'), 'extract')
2427
.then(() => t.matchSnapshot(require(pj), 'package.json extracted'))

test/git.js

+2
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ t.test('basic stuff', async t => {
255255
t.throws(() => fs.statSync(me + '/g/prepare.js'))
256256

257257
const gm = await g.manifest()
258+
t.equal(gm, g.package)
258259
t.match(gm, {
259260
name: 'repo',
260261
version: '1.0.0',
@@ -271,6 +272,7 @@ t.test('basic stuff', async t => {
271272
_integrity: `${g.integrity}`,
272273
_resolved: `${remote}#${g.resolvedSha}`,
273274
})
275+
t.equal(await g.manifest(), gm, 'cached manifest')
274276

275277
// one that doesn't have an npm install step, but does have submods
276278
const subs = new GitFetcher(submodsRemote, {cache})

test/registry.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ t.test('underscore, no tag or version', t => {
6464
const f = new RegistryFetcher('underscore', {registry, cache})
6565

6666
return f.resolve().then(r => t.equal(r, `${registry}underscore/-/underscore-1.5.1.tgz`))
67-
.then(() => f.manifest()).then(m => t.match(m, { version: '1.5.1' }))
67+
.then(() => f.manifest()).then(m => {
68+
t.equal(m, f.package)
69+
t.match(m, { version: '1.5.1' })
70+
return f.manifest().then(m2 => t.equal(m, m2, 'manifest cached'))
71+
})
6872
.then(() => f.extract(me + '/underscore'))
6973
.then(result => t.deepEqual(result, {
7074
resolved: `${registry}underscore/-/underscore-1.5.1.tgz`,

0 commit comments

Comments
 (0)