diff --git a/README.md b/README.md index 3b230d6b..c001a228 100644 --- a/README.md +++ b/README.md @@ -297,9 +297,9 @@ cacache.get.info(cachePath, 'my-thing').then(console.log) #### `> cacache.get.hasContent(cache, integrity) -> Promise` -Looks up a [Subresource Integrity hash](#integrity) in the cache. If content -exists for this `integrity`, it will return the specific single integrity hash -that was found. If no content exists for this integrity, it will return `false`. +Looks up a [Subresource Integrity hash](#integrity) in the cache. If content +exists for this `integrity`, it will return an object, with the specific single integrity hash +that was found in `sri` key, and the size of the found content as `size`. If no content exists for this integrity, it will return `false`. ##### Fields @@ -316,10 +316,13 @@ cacache.get.hasContent(cachePath, 'sha256-MUSTVERIFY+ALL/THINGS==').then(console // Output { - source: 'sha256-MUSTVERIFY+ALL/THINGS==', - algorithm: 'sha256', - digest: 'MUSTVERIFY+ALL/THINGS==', - options: [] + sri: { + source: 'sha256-MUSTVERIFY+ALL/THINGS==', + algorithm: 'sha256', + digest: 'MUSTVERIFY+ALL/THINGS==', + options: [] + }, + size: 9001 } cacache.get.hasContent(cachePath, 'sha521-NOT+IN/CACHE==').then(console.log) @@ -397,7 +400,7 @@ for inserted data. Can use any algorithm listed in `crypto.getHashes()` or `'omakase'`/`'お任せします'` to pick a random hash algorithm on each insertion. You may also use any anagram of `'modnar'` to use this feature. -Currently only supports one algorithm at a time (i.e., an array length of +Currently only supports one algorithm at a time (i.e., an array length of exactly `1`). Has no effect if `opts.integrity` is present. ##### `opts.uid`/`opts.gid` diff --git a/lib/content/read.js b/lib/content/read.js index 5721c05b..0ba19ac6 100644 --- a/lib/content/read.js +++ b/lib/content/read.js @@ -13,7 +13,8 @@ BB.promisifyAll(fs) module.exports = read function read (cache, integrity, opts) { opts = opts || {} - return pickContentSri(cache, integrity).then(sri => { + return pickContentSri(cache, integrity).then(content => { + const sri = content.sri const cpath = contentPath(cache, sri) return fs.readFileAsync(cpath, null).then(data => { if (typeof opts.size === 'number' && opts.size !== data.length) { @@ -34,7 +35,8 @@ function readStream (cache, integrity, opts) { const stream = new PassThrough() pickContentSri( cache, integrity - ).then(sri => { + ).then(content => { + const sri = content.sri return pipe( fs.createReadStream(contentPath(cache, sri)), ssri.integrityStream({ @@ -52,7 +54,7 @@ function readStream (cache, integrity, opts) { module.exports.hasContent = hasContent function hasContent (cache, integrity) { if (!integrity) { return BB.resolve(false) } - return pickContentSri(cache, integrity, true) + return pickContentSri(cache, integrity) .catch({code: 'ENOENT'}, () => false) .catch({code: 'EPERM'}, err => { if (process.platform !== 'win32') { @@ -60,11 +62,14 @@ function hasContent (cache, integrity) { } else { return false } - }).then(sri => sri || false) + }).then(content => { + if (!content.sri) return false + return ({ sri: content.sri, size: content.stat.size }) + }) } module.exports._pickContentSri = pickContentSri -function pickContentSri (cache, integrity, checkFs) { +function pickContentSri (cache, integrity) { const sri = ssri.parse(integrity) // If `integrity` has multiple entries, pick the first digest // with available local data. @@ -72,14 +77,10 @@ function pickContentSri (cache, integrity, checkFs) { const digests = sri[algo] if (digests.length <= 1) { const cpath = contentPath(cache, digests[0]) - if (checkFs) { - return fs.lstatAsync(cpath).then(() => digests[0]) - } else { - return BB.resolve(digests[0]) - } + return fs.lstatAsync(cpath).then(stat => ({ sri: digests[0], stat })) } else { return BB.any(sri[sri.pickAlgorithm()].map(meta => { - return pickContentSri(cache, meta, true) + return pickContentSri(cache, meta) })) } } diff --git a/lib/content/rm.js b/lib/content/rm.js index 4893b9a6..a8903dc0 100644 --- a/lib/content/rm.js +++ b/lib/content/rm.js @@ -8,7 +8,8 @@ const rimraf = BB.promisify(require('rimraf')) module.exports = rm function rm (cache, integrity) { - return hasContent(cache, integrity).then(sri => { + return hasContent(cache, integrity).then(content => { + const sri = content.sri if (sri) { return rimraf(contentPath(cache, sri)) } diff --git a/test/content.read.js b/test/content.read.js index 54d42d26..3f9f24e0 100644 --- a/test/content.read.js +++ b/test/content.read.js @@ -132,17 +132,18 @@ test('read: errors if content size does not match size option', function (t) { ) }) -test('hasContent: returns true when a cache file exists', function (t) { +test('hasContent: returns { sri, size } when a cache file exists', function (t) { const fixture = new Tacks(CacheContent({ 'sha1-deadbeef': '' })) fixture.create(CACHE) return BB.join( - read.hasContent(CACHE, 'sha1-deadbeef').then(bool => { - t.ok(bool, 'returned true for existing content') + read.hasContent(CACHE, 'sha1-deadbeef').then(content => { + t.ok(content.sri, 'returned sri for this content') + t.equal(content.size, 0, 'returned the right size for this content') }), - read.hasContent(CACHE, 'sha1-not-there').then(bool => { - t.equal(bool, false, 'returned false for missing content') + read.hasContent(CACHE, 'sha1-not-there').then(content => { + t.equal(content, false, 'returned false for missing content') }) ) })