[6a3a178] | 1 | const Fetcher = require('./fetcher.js')
|
---|
| 2 | const fsm = require('fs-minipass')
|
---|
| 3 | const cacache = require('cacache')
|
---|
| 4 | const { promisify } = require('util')
|
---|
| 5 | const readPackageJson = require('read-package-json-fast')
|
---|
| 6 | const _tarballFromResolved = Symbol.for('pacote.Fetcher._tarballFromResolved')
|
---|
| 7 | const _exeBins = Symbol('_exeBins')
|
---|
| 8 | const { resolve } = require('path')
|
---|
| 9 | const fs = require('fs')
|
---|
| 10 |
|
---|
| 11 | class FileFetcher extends Fetcher {
|
---|
| 12 | constructor (spec, opts) {
|
---|
| 13 | super(spec, opts)
|
---|
| 14 | // just the fully resolved filename
|
---|
| 15 | this.resolved = this.spec.fetchSpec
|
---|
| 16 | }
|
---|
| 17 |
|
---|
| 18 | get types () {
|
---|
| 19 | return ['file']
|
---|
| 20 | }
|
---|
| 21 |
|
---|
| 22 | manifest () {
|
---|
| 23 | if (this.package)
|
---|
| 24 | return Promise.resolve(this.package)
|
---|
| 25 |
|
---|
| 26 | // have to unpack the tarball for this.
|
---|
| 27 | return cacache.tmp.withTmp(this.cache, this.opts, dir =>
|
---|
| 28 | this.extract(dir)
|
---|
| 29 | .then(() => readPackageJson(dir + '/package.json'))
|
---|
| 30 | .then(mani => this.package = {
|
---|
| 31 | ...mani,
|
---|
| 32 | _integrity: this.integrity && String(this.integrity),
|
---|
| 33 | _resolved: this.resolved,
|
---|
| 34 | _from: this.from,
|
---|
| 35 | }))
|
---|
| 36 | }
|
---|
| 37 |
|
---|
| 38 | [_exeBins] (pkg, dest) {
|
---|
| 39 | if (!pkg.bin)
|
---|
| 40 | return Promise.resolve()
|
---|
| 41 |
|
---|
| 42 | return Promise.all(Object.keys(pkg.bin).map(k => new Promise(res => {
|
---|
| 43 | const script = resolve(dest, pkg.bin[k])
|
---|
| 44 | // Best effort. Ignore errors here, the only result is that
|
---|
| 45 | // a bin script is not executable. But if it's missing or
|
---|
| 46 | // something, we just leave it for a later stage to trip over
|
---|
| 47 | // when we can provide a more useful contextual error.
|
---|
| 48 | fs.stat(script, (er, st) => {
|
---|
| 49 | if (er)
|
---|
| 50 | return res()
|
---|
| 51 | const mode = st.mode | 0o111
|
---|
| 52 | if (mode === st.mode)
|
---|
| 53 | return res()
|
---|
| 54 | fs.chmod(script, mode, res)
|
---|
| 55 | })
|
---|
| 56 | })))
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 | extract (dest) {
|
---|
| 60 | // if we've already loaded the manifest, then the super got it.
|
---|
| 61 | // but if not, read the unpacked manifest and chmod properly.
|
---|
| 62 | return super.extract(dest)
|
---|
| 63 | .then(result => this.package ? result
|
---|
| 64 | : readPackageJson(dest + '/package.json').then(pkg =>
|
---|
| 65 | this[_exeBins](pkg, dest)).then(() => result))
|
---|
| 66 | }
|
---|
| 67 |
|
---|
| 68 | [_tarballFromResolved] () {
|
---|
| 69 | // create a read stream and return it
|
---|
| 70 | return new fsm.ReadStream(this.resolved)
|
---|
| 71 | }
|
---|
| 72 |
|
---|
| 73 | packument () {
|
---|
| 74 | // simulate based on manifest
|
---|
| 75 | return this.manifest().then(mani => ({
|
---|
| 76 | name: mani.name,
|
---|
| 77 | 'dist-tags': {
|
---|
| 78 | [this.defaultTag]: mani.version
|
---|
| 79 | },
|
---|
| 80 | versions: {
|
---|
| 81 | [mani.version]: {
|
---|
| 82 | ...mani,
|
---|
| 83 | dist: {
|
---|
| 84 | tarball: `file:${this.resolved}`,
|
---|
| 85 | integrity: this.integrity && String(this.integrity),
|
---|
| 86 | }
|
---|
| 87 | }
|
---|
| 88 | }
|
---|
| 89 | }))
|
---|
| 90 | }
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | module.exports = FileFetcher
|
---|