test('works fine if entry missing', function (t) { const fixture = new Tacks(CacheContent({})) fixture.create(CACHE) return rm(CACHE, 'sha1-deadbeef').then(() => ( fs.statAsync(contentPath(CACHE, 'sha1-deadbeef')) )).then(() => { throw new Error('expected an error') }).catch(err => { t.ok(err, 'fs.stat failed on rmed content') t.equal('ENOENT', err.code, 'file does not exist anymore') }) })
fs.statAsync(f) .then(stat => stat.size > 28)
test('creates a unique tmpdir inside the cache', t => { return tmp.mkdir(CACHE).then(dir => { t.match(path.relative(CACHE, dir), /^tmp[\\/].*/, 'returns a path inside tmp') return fs.statAsync(dir) }).then(stat => { t.ok(stat.isDirectory(), 'path points to an existing directory') }) })
function verifyContent (filepath, sri) { return fs.statAsync(filepath).then(stat => { const contentInfo = { size: stat.size, valid: true } return ssri.checkStream( fs.createReadStream(filepath), sri ).catch(err => { if (err.code !== 'EINTEGRITY') { throw err } return rimraf(filepath).then(() => { contentInfo.valid = false }) }).then(() => contentInfo) }).catch({ code: 'ENOENT' }, () => ({ size: 0, valid: false })) }
function rebuildBucket (cache, bucket, stats, opts) { return fs.truncateAsync(bucket._path).then(() => { // This needs to be serialized because cacache explicitly // lets very racy bucket conflicts clobber each other. return BB.mapSeries(bucket, entry => { const content = contentPath(cache, entry.integrity) return fs.statAsync(content).then(() => { return index.insert(cache, entry.key, entry.integrity, { uid: opts.uid, gid: opts.gid, metadata: entry.metadata, size: entry.size }).then(() => { stats.totalEntries++ }) }).catch({ code: 'ENOENT' }, () => { stats.rejectedEntries++ stats.missingContent++ }) }) }) }
test('cleans up contents of tmp dir', t => { const tmpFile = path.join(CACHE, 'tmp', 'x') const misc = path.join(CACHE, 'y') return mockCache().then(() => { return BB.join( fs.writeFileAsync(tmpFile, ''), fs.writeFileAsync(misc, ''), () => verify(CACHE) ) }).then(() => { return BB.join( fs.statAsync(tmpFile).catch({ code: 'ENOENT' }, e => e), fs.statAsync(misc), (err, stat) => { t.equal(err.code, 'ENOENT', 'tmp file was blown away') t.ok(stat, 'misc file was not touched') } ) }) })
return fs.statAsync(f).then(s => { return rimraf(f).then(() => { stats.reclaimedSize += s.size
test('provides a utility that does resource disposal on tmp', t => { return tmp.withTmp(CACHE, dir => { return fs.statAsync(dir).then(stat => { t.ok(stat.isDirectory(), 'path points to an existing directory') }).then(() => dir) }).then(dir => { return BB.join( fs.statAsync(dir).then(() => { throw new Error('expected fail') }).catch({ code: 'ENOENT' }, () => {}), fs.statAsync(path.join(CACHE, 'tmp')), (nope, yes) => { t.notOk(nope, 'tmp subdir removed') t.ok(yes.isDirectory(), 'tmp parent dir left intact') } ) }) })
test('removes corrupted content', t => { const cpath = contentPath(CACHE, INTEGRITY) return mockCache().then(() => { return fs.truncateAsync(cpath, CONTENT.length - 1) }).then(() => { return verify(CACHE) }).then(stats => { delete stats.startTime delete stats.runTime delete stats.endTime t.deepEqual(stats, { verifiedContent: 0, reclaimedCount: 1, reclaimedSize: CONTENT.length - 1, badContentCount: 1, keptSize: 0, missingContent: 1, rejectedEntries: 1, totalEntries: 0 }, 'reported correct collection counts') return fs.statAsync(cpath).then(() => { throw new Error('expected a failure') }).catch({ code: 'ENOENT' }, err => { t.match(err.message, /no such file/, 'content no longer in cache') }) }) })
t.equal(code, 0, 'npm pack exited ok') t.match(stdout, /generic-package-90000\.100001\.5\.tgz/ig, 'found pkg') return fs.statAsync( path.join(testDir, 'generic-package-90000.100001.5.tgz')
test('basic pack', (t) => { const fixture = new Tacks(new Dir({ 'package.json': new File({ name: 'generic-package', version: '90000.100001.5' }) })) return rimraf(testDir) .then(() => fixture.create(testDir)) .then(() => common.npm([ 'pack', '--loglevel', 'notice', '--cache', cache, '--tmp', tmp, '--prefix', testDir, '--no-global' ], { cwd: testDir })) .spread((code, stdout, stderr) => { t.equal(code, 0, 'npm pack exited ok') t.match(stderr, /notice\s+\d+[a-z]+\s+package\.json/gi, 'mentions package.json') t.match(stdout, /generic-package-90000\.100001\.5\.tgz/ig, 'found pkg') return fs.statAsync( path.join(testDir, 'generic-package-90000.100001.5.tgz') ) }) .then((stat) => t.ok(stat, 'tarball written to cwd')) .then(() => rimraf(testDir)) })
.spread((code, stdout, stderr) => { t.equal(code, 0, 'npm pack exited ok') return fs.statAsync( path.join(testDir, 'postpack-step')
test('removes a content entry', function (t) { const fixture = new Tacks(CacheContent({ 'sha1-deadbeef': '' })) fixture.create(CACHE) return rm(CACHE, 'sha1-deadbeef').then(() => ( fs.statAsync(contentPath(CACHE, 'sha1-deadbeef')) )).then(() => { throw new Error('expected an error') }).catch(err => { t.ok(err, 'fs.stat failed on rmed content') t.equal('ENOENT', err.code, 'file does not exist anymore') }) })