diff options
Diffstat (limited to 'deps/npm/node_modules/cacache/lib/content/read.js')
-rw-r--r-- | deps/npm/node_modules/cacache/lib/content/read.js | 139 |
1 files changed, 102 insertions, 37 deletions
diff --git a/deps/npm/node_modules/cacache/lib/content/read.js b/deps/npm/node_modules/cacache/lib/content/read.js index 5c1a6f2f29..8f1acc06d8 100644 --- a/deps/npm/node_modules/cacache/lib/content/read.js +++ b/deps/npm/node_modules/cacache/lib/content/read.js @@ -10,7 +10,8 @@ const pipe = BB.promisify(require('mississippi').pipe) const ssri = require('ssri') const Y = require('../util/y.js') -BB.promisifyAll(fs) +const lstatAsync = BB.promisify(fs.lstat) +const readFileAsync = BB.promisify(fs.readFile) const ReadOpts = figgyPudding({ size: {} @@ -19,10 +20,8 @@ const ReadOpts = figgyPudding({ module.exports = read function read (cache, integrity, opts) { opts = ReadOpts(opts) - return pickContentSri(cache, integrity).then(content => { - const sri = content.sri - const cpath = contentPath(cache, sri) - return fs.readFileAsync(cpath, null).then(data => { + return withContentSri(cache, integrity, (cpath, sri) => { + return readFileAsync(cpath, null).then(data => { if (typeof opts.size === 'number' && opts.size !== data.length) { throw sizeError(opts.size, data.length) } else if (ssri.checkData(data, sri)) { @@ -34,17 +33,31 @@ function read (cache, integrity, opts) { }) } +module.exports.sync = readSync +function readSync (cache, integrity, opts) { + opts = ReadOpts(opts) + return withContentSriSync(cache, integrity, (cpath, sri) => { + const data = fs.readFileSync(cpath) + if (typeof opts.size === 'number' && opts.size !== data.length) { + throw sizeError(opts.size, data.length) + } else if (ssri.checkData(data, sri)) { + return data + } else { + throw integrityError(sri, cpath) + } + }) +} + module.exports.stream = readStream module.exports.readStream = readStream function readStream (cache, integrity, opts) { opts = ReadOpts(opts) const stream = new PassThrough() - pickContentSri( - cache, integrity - ).then(content => { - const sri = content.sri + withContentSri(cache, integrity, (cpath, sri) => { + return lstatAsync(cpath).then(stat => ({cpath, sri, stat})) + }).then(({cpath, sri, stat}) => { return pipe( - fs.createReadStream(contentPath(cache, sri)), + fs.createReadStream(cpath), ssri.integrityStream({ integrity: sri, size: opts.size @@ -57,37 +70,93 @@ function readStream (cache, integrity, opts) { return stream } +let copyFileAsync if (fs.copyFile) { module.exports.copy = copy + module.exports.copy.sync = copySync + copyFileAsync = BB.promisify(fs.copyFile) } + function copy (cache, integrity, dest, opts) { opts = ReadOpts(opts) - return pickContentSri(cache, integrity).then(content => { - const sri = content.sri - const cpath = contentPath(cache, sri) - return fs.copyFileAsync(cpath, dest).then(() => content.size) + return withContentSri(cache, integrity, (cpath, sri) => { + return copyFileAsync(cpath, dest) + }) +} + +function copySync (cache, integrity, dest, opts) { + opts = ReadOpts(opts) + return withContentSriSync(cache, integrity, (cpath, sri) => { + return fs.copyFileSync(cpath, dest) }) } module.exports.hasContent = hasContent function hasContent (cache, integrity) { if (!integrity) { return BB.resolve(false) } - return pickContentSri(cache, integrity) - .catch({code: 'ENOENT'}, () => false) - .catch({code: 'EPERM'}, err => { + return withContentSri(cache, integrity, (cpath, sri) => { + return lstatAsync(cpath).then(stat => ({size: stat.size, sri, stat})) + }).catch(err => { + if (err.code === 'ENOENT') { return false } + if (err.code === 'EPERM') { if (process.platform !== 'win32') { throw err } else { return false } - }).then(content => { - if (!content.sri) return false - return ({ sri: content.sri, size: content.stat.size }) - }) + } + }) } -module.exports._pickContentSri = pickContentSri -function pickContentSri (cache, integrity) { +module.exports.hasContent.sync = hasContentSync +function hasContentSync (cache, integrity) { + if (!integrity) { return false } + return withContentSriSync(cache, integrity, (cpath, sri) => { + try { + const stat = fs.lstatSync(cpath) + return {size: stat.size, sri, stat} + } catch (err) { + if (err.code === 'ENOENT') { return false } + if (err.code === 'EPERM') { + if (process.platform !== 'win32') { + throw err + } else { + return false + } + } + } + }) +} + +function withContentSri (cache, integrity, fn) { + return BB.try(() => { + const sri = ssri.parse(integrity) + // If `integrity` has multiple entries, pick the first digest + // with available local data. + const algo = sri.pickAlgorithm() + const digests = sri[algo] + if (digests.length <= 1) { + const cpath = contentPath(cache, digests[0]) + return fn(cpath, digests[0]) + } else { + return BB.any(sri[sri.pickAlgorithm()].map(meta => { + return withContentSri(cache, meta, fn) + }, {concurrency: 1})) + .catch(err => { + if ([].some.call(err, e => e.code === 'ENOENT')) { + throw Object.assign( + new Error('No matching content found for ' + sri.toString()), + {code: 'ENOENT'} + ) + } else { + throw err[0] + } + }) + } + }) +} + +function withContentSriSync (cache, integrity, fn) { const sri = ssri.parse(integrity) // If `integrity` has multiple entries, pick the first digest // with available local data. @@ -95,21 +164,17 @@ function pickContentSri (cache, integrity) { const digests = sri[algo] if (digests.length <= 1) { const cpath = contentPath(cache, digests[0]) - return fs.lstatAsync(cpath).then(stat => ({ sri: digests[0], stat })) + return fn(cpath, digests[0]) } else { - return BB.any(sri[sri.pickAlgorithm()].map(meta => { - return pickContentSri(cache, meta) - })) - .catch(err => { - if ([].some.call(err, e => e.code === 'ENOENT')) { - throw Object.assign( - new Error('No matching content found for ' + sri.toString()), - {code: 'ENOENT'} - ) - } else { - throw err[0] - } - }) + let lastErr = null + for (const meta of sri[sri.pickAlgorithm()]) { + try { + return withContentSriSync(cache, meta, fn) + } catch (err) { + lastErr = err + } + } + if (lastErr) { throw lastErr } } } |