Skip to content
This repository has been archived by the owner on Jul 3, 2019. It is now read-only.

Commit

Permalink
feat(read): change hasContent to return {sri, size} (#88)
Browse files Browse the repository at this point in the history
Fixes #87

BREAKING CHANGE: hasContent now returns an object with `{sri, size}` instead of `sri`. Use `result.sri` anywhere that needed the old return value.
  • Loading branch information
Alexander Plavinski authored and zkat committed Apr 22, 2017
1 parent a9130de commit bad6c49
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 25 deletions.
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,9 @@ cacache.get.info(cachePath, 'my-thing').then(console.log)

#### <a name="get-hasContent"></a> `> 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

Expand All @@ -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)
Expand Down Expand Up @@ -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`
Expand Down
23 changes: 12 additions & 11 deletions lib/content/read.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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({
Expand All @@ -52,34 +54,33 @@ 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') {
throw err
} 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.
const algo = sri.pickAlgorithm()
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)
}))
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/content/rm.js
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
11 changes: 6 additions & 5 deletions test/content.read.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
)
})

0 comments on commit bad6c49

Please sign in to comment.