Skip to content

Commit

Permalink
feat(rm): limited rm.all and fixed bugs (#66)
Browse files Browse the repository at this point in the history
Fixes: #65
  • Loading branch information
zkat authored Mar 11, 2017
1 parent 3a21b2f commit d5d25ba
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 6 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,8 @@ cacache.rm.all(cachePath).then(() => {

#### <a name="rm-entry"></a> `> cacache.rm.entry(cache, key) -> Promise`

Alias: `cacache.rm`

Removes the index entry for `key`. Content will still be accessible if
requested directly by content address ([`get.stream.byDigest`](#get-stream)).

Expand Down
2 changes: 2 additions & 0 deletions lib/entry-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ function hashKey (key) {
}

function formatEntry (cache, entry) {
// Treat null digests as deletions. They'll shadow any previous entries.
if (!entry.digest) { return null }
return {
key: entry.key,
digest: entry.digest,
Expand Down
14 changes: 8 additions & 6 deletions rm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@ const Promise = require('bluebird')

const index = require('./lib/entry-index')
const memo = require('./lib/memoization')
const path = require('path')
const rimraf = Promise.promisify(require('rimraf'))
const rmContent = require('./lib/content/rm')

module.exports.all = all
function all (cache) {
memo.clearMemoized()
return rimraf(cache)
}

module.exports = entry
module.exports.entry = entry
function entry (cache, key) {
memo.clearMemoized()
Expand All @@ -24,3 +20,9 @@ function content (cache, address) {
memo.clearMemoized()
return rmContent(cache, address)
}

module.exports.all = all
function all (cache) {
memo.clearMemoized()
return rimraf(path.join(cache, '*(content-*|index-*)'))
}
106 changes: 106 additions & 0 deletions test/rm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
'use strict'

const Promise = require('bluebird')

const crypto = require('crypto')
const fromString = require('./util/from-string')
const fs = Promise.promisifyAll(require('fs'))
const index = require('../lib/entry-index')
const memo = require('../lib/memoization')
const path = require('path')
const pipe = Promise.promisify(require('mississippi').pipe)
const Tacks = require('tacks')
const test = require('tap').test
const testDir = require('./util/test-dir')(__filename)

const CacheContent = require('./util/cache-content')
const CACHE = path.join(testDir, 'cache')
const CONTENT = bufferise('foobarbaz')
const KEY = 'my-test-key'
const ALGO = 'sha512'
const DIGEST = crypto.createHash(ALGO).update(CONTENT).digest('hex')
const METADATA = { foo: 'bar' }
const contentPath = require('../lib/content/path')

const get = require('../get')

const rm = require('../rm')

function bufferise (string) {
return Buffer.from
? Buffer.from(string, 'utf8')
: new Buffer(string, 'utf8')
}

test('rm.entry removes entries, not content', t => {
const fixture = new Tacks(CacheContent({
[DIGEST]: CONTENT
}, ALGO))
fixture.create(CACHE)
return index.insert(CACHE, KEY, DIGEST, {
metadata: METADATA,
hashAlgorithm: ALGO
}).then(() => {
t.equal(rm, rm.entry, 'rm is an alias for rm.entry')
return rm.entry(CACHE, KEY)
}).then(() => {
return get(CACHE, KEY)
}).then(res => {
throw new Error('unexpected success')
}).catch({code: 'ENOENT'}, err => {
t.match(err.message, /not found/, 'entry no longer accessible')
}).then(() => {
return fs.readFileAsync(contentPath(CACHE, DIGEST, ALGO))
}).then(data => {
t.deepEqual(data, CONTENT, 'content remains in cache')
})
})

test('rm.content removes content, not entries', t => {
const fixture = new Tacks(CacheContent({
[DIGEST]: CONTENT
}, ALGO))
fixture.create(CACHE)
return index.insert(CACHE, KEY, DIGEST, {
metadata: METADATA,
hashAlgorithm: ALGO
}).then(() => {
return rm.content(CACHE, DIGEST)
}).then(() => {
return get(CACHE, KEY)
}).then(res => {
throw new Error('unexpected success')
}).catch({code: 'ENOENT'}, err => {
t.match(err.message, /no such file/, 'entry no longer accessible')
}).then(() => {
return fs.readFileAsync(contentPath(CACHE, DIGEST, ALGO))
}).then(() => {
throw new Error('unexpected success')
}).catch({code: 'ENOENT'}, err => {
t.match(err.message, /no such file/, 'content gone')
})
})

test('rm.all deletes content and index dirs', t => {
const fixture = new Tacks(CacheContent({
[DIGEST]: CONTENT
}, ALGO))
fixture.create(CACHE)
return index.insert(CACHE, KEY, DIGEST, {
metadata: METADATA,
hashAlgorithm: ALGO
}).then(() => {
return fs.mkdirAsync(path.join(CACHE, 'tmp'))
}).then(() => {
return fs.writeFileAsync(path.join(CACHE, 'other.js'), 'hi')
}).then(() => {
return rm.all(CACHE)
}).then(() => {
return fs.readdirAsync(CACHE)
}).then(files => {
t.deepEqual(files.sort(), [
'other.js',
'tmp'
], 'removes content and index directories without touching other stuff')
})
})

0 comments on commit d5d25ba

Please sign in to comment.