cacache
Advanced tools
Comparing version 3.0.1 to 4.0.0
31
get.js
@@ -1,2 +0,1 @@ | ||
var fs = require('graceful-fs') | ||
var index = require('./lib/entry-index') | ||
@@ -18,2 +17,6 @@ var pipe = require('mississippi').pipe | ||
} | ||
stream.emit('metadata', data) | ||
stream.on('newListener', function (ev, cb) { | ||
ev === 'metadata' && cb(data) | ||
}) | ||
pipe( | ||
@@ -27,28 +30,2 @@ read.readStream(cache, data.digest, opts), | ||
module.exports.file = file | ||
function file (cache, key, destination, opts, cb) { | ||
if (!cb) { | ||
cb = opts | ||
opts = {} | ||
} | ||
pipe( | ||
stream(cache, key, opts), | ||
fs.createWriteStream(destination), | ||
cb | ||
) | ||
} | ||
file.byDigest = fileByDigest | ||
function fileByDigest (cache, digest, destination, opts, cb) { | ||
if (!cb) { | ||
cb = opts | ||
opts = {} | ||
} | ||
pipe( | ||
stream.byDigest(cache, digest, opts), | ||
fs.createWriteStream(destination), | ||
cb | ||
) | ||
} | ||
module.exports.info = info | ||
@@ -55,0 +32,0 @@ function info (cache, key, cb) { |
var checkSizeStream = require('../util/check-size-stream') | ||
var checksumStream = require('../util/checksum-stream') | ||
var contentPath = require('./path') | ||
var dezalgo = require('dezalgo') | ||
var duplex = require('mississippi').duplex | ||
var fixOwner = require('../util/fix-owner') | ||
@@ -9,41 +9,38 @@ var fs = require('graceful-fs') | ||
var moveFile = require('../util/move-file') | ||
var once = require('once') | ||
var path = require('path') | ||
var pipe = require('mississippi').pipe | ||
var pipeline = require('mississippi').pipeline | ||
var randomstring = require('randomstring') | ||
var rimraf = require('rimraf') | ||
var through = require('mississippi').through | ||
var to = require('mississippi').to | ||
module.exports = putStream | ||
function putStream (cache, inputStream, opts, _cb) { | ||
if (!_cb) { | ||
_cb = opts | ||
opts = null | ||
} | ||
function putStream (cache, opts) { | ||
opts = opts || {} | ||
var tmpTarget = path.join(cache, 'tmp', (opts.tmpPrefix || '') + randomstring.generate()) | ||
var cb = dezalgo(once(function (err, digest) { | ||
rimraf(tmpTarget, function (err2) { | ||
return _cb(err2 || err, digest) | ||
}) | ||
})) | ||
inputStream.on('error', cb) | ||
var inputStream = duplex() | ||
inputStream.on('error', function () { | ||
rimraf(tmpTarget, function () {}) | ||
}) | ||
hasContent(cache, opts.digest, function (err, exists) { | ||
if (err) { return cb(err) } | ||
if (err) { | ||
return errify(tmpTarget, inputStream, err, function () {}) | ||
} | ||
// Fast-path-shortcut this if it's already been written. | ||
if (exists) { | ||
return cb(err, opts.digest) | ||
inputStream.emit('digest', opts.digest) | ||
inputStream.setWritable(to(function (c, en, cb) { | ||
cb() | ||
})) | ||
return | ||
} | ||
pipeToTmp(inputStream, tmpTarget, opts, function (err, digest) { | ||
if (err) { return cb(err) } | ||
moveToDestination(tmpTarget, cache, digest, opts, function (err) { | ||
if (err) { return cb(err) } | ||
cb(null, digest) | ||
}) | ||
}) | ||
pipeToTmp(inputStream, cache, tmpTarget, opts) | ||
}) | ||
return inputStream | ||
} | ||
function pipeToTmp (inputStream, tmpTarget, opts, cb) { | ||
function pipeToTmp (inputStream, cache, tmpTarget, opts, cb) { | ||
fixOwner.mkdirfix(path.dirname(tmpTarget), opts.uid, opts.gid, function (err) { | ||
@@ -56,29 +53,39 @@ if (err) { return cb(err) } | ||
var digest | ||
hashStream.on('digest', function (d) { digest = d }) | ||
var gotData = false | ||
hashStream.on('digest', function (d) { | ||
digest = d | ||
}) | ||
var outStream = fs.createWriteStream(tmpTarget) | ||
inputStream.on('data', function dataCheck () { | ||
var gotData | ||
var teed = to(function (chunk, enc, cb) { | ||
gotData = true | ||
inputStream.removeListener('data', dataCheck) | ||
}) | ||
pipe( | ||
inputStream, | ||
sizeStream, | ||
hashStream, | ||
outStream, | ||
function (err) { | ||
if (err) { return cb(err) } | ||
outStream.write(chunk, enc, cb) | ||
}, function (cb) { | ||
outStream.end(function () { | ||
if (!gotData) { | ||
var e = new Error('Input stream empty') | ||
e.code = 'ENODATA' | ||
e.stream = inputStream | ||
return cb(e) | ||
return errify(tmpTarget, inputStream, e, function () {}) | ||
} | ||
cb(null, digest) | ||
} | ||
) | ||
moveToDestination(tmpTarget, cache, digest, opts, function (err) { | ||
if (err) { return cb(err) } | ||
inputStream.emit('digest', digest) | ||
rimraf(tmpTarget, cb) | ||
}) | ||
}) | ||
}) | ||
var combined = pipeline(sizeStream, hashStream, teed) | ||
outStream.on('error', function (err) { | ||
errify(tmpTarget, inputStream, err, function () {}) | ||
}) | ||
inputStream.setWritable(combined) | ||
}) | ||
} | ||
function errify (file, stream, err, cb) { | ||
rimraf(file, function () { | ||
stream.emit('error', err) | ||
cb && cb() | ||
}) | ||
} | ||
function moveToDestination (tmpTarget, cache, digest, opts, cb) { | ||
@@ -85,0 +92,0 @@ var destination = contentPath(cache, digest) |
@@ -10,3 +10,3 @@ var checksumStream = require('../util/checksum-stream') | ||
opts = opts || {} | ||
var stream = checksumStream(address, opts.hashAlgorithm || 'sha256') | ||
var stream = checksumStream(address, opts.hashAlgorithm || 'sha1') | ||
var cpath = contentPath(cache, address) | ||
@@ -13,0 +13,0 @@ hasContent(cache, address, function (err, exists) { |
@@ -6,3 +6,3 @@ var crypto = require('crypto') | ||
function checksumStream (digest, algorithm) { | ||
var hash = crypto.createHash(algorithm || 'sha256') | ||
var hash = crypto.createHash(algorithm || 'sha1') | ||
var stream = through(function (chunk, enc, cb) { | ||
@@ -9,0 +9,0 @@ hash.update(chunk, enc) |
@@ -113,3 +113,3 @@ var asyncMap = require('slide').asyncMap | ||
if (byDigest[f]) { | ||
var algo = opts.hashAlgorithm || 'sha256' | ||
var algo = opts.hashAlgorithm || 'sha1' | ||
verifyContent(fullPath, algo, function (err, collected) { | ||
@@ -116,0 +116,0 @@ if (err) { return cb(err) } |
{ | ||
"name": "cacache", | ||
"version": "3.0.1", | ||
"version": "4.0.0", | ||
"description": "General content-addressable cache system that maintains a filesystem registry of file data.", | ||
@@ -43,3 +43,3 @@ "main": "index.js", | ||
"tacks": "^1.2.2", | ||
"tap": "^8.0.1" | ||
"tap": "^9.0.3" | ||
}, | ||
@@ -46,0 +46,0 @@ "config": { |
76
put.js
@@ -1,72 +0,16 @@ | ||
var dezalgo = require('dezalgo') | ||
var from = require('mississippi').from | ||
var fs = require('graceful-fs') | ||
var index = require('./lib/entry-index') | ||
var inflight = require('inflight') | ||
var path = require('path') | ||
var putContentStream = require('./lib/content/put-stream') | ||
var putContent = require('./lib/content/put-stream') | ||
var to = require('mississippi').to | ||
module.exports.file = putFile | ||
function putFile (cache, key, filePath, opts, cb) { | ||
if (!cb) { | ||
cb = opts | ||
opts = null | ||
} | ||
cb = dezalgo(cb) | ||
opts = Object.create(opts || {}) | ||
opts.filename = opts.filename || path.basename(filePath) | ||
try { | ||
var stream = fs.createReadStream(filePath) | ||
} catch (e) { | ||
return cb(e) | ||
} | ||
return putStream(cache, key, stream, opts, cb) | ||
} | ||
module.exports.data = putData | ||
function putData (cache, key, filename, data, opts, cb) { | ||
if (!cb) { | ||
cb = opts | ||
opts = null | ||
} | ||
opts = Object.create(opts || {}) | ||
opts.filename = filename | ||
var stream = from(function (size, next) { | ||
if (data.length <= 0) return next(null, null) | ||
var chunk = data.slice(0, size) | ||
data = data.slice(size) | ||
next(null, chunk) | ||
}) | ||
return putStream(cache, key, stream, opts, cb) | ||
} | ||
module.exports.stream = putStream | ||
function putStream (cache, key, inputStream, opts, cb) { | ||
if (!cb) { | ||
cb = opts | ||
opts = null | ||
} | ||
cb = inflight('cacache.put.stream: ' + key, cb) | ||
if (!cb) { return } | ||
return putContentStream(cache, inputStream, opts, function (err, digest) { | ||
if (err) { cb(err) } | ||
index.insert(cache, key, digest, opts, function (err) { | ||
cb(err, digest) | ||
}) | ||
function putStream (cache, key, opts) { | ||
var digest | ||
var contentStream = putContent(cache, opts).on('digest', function (d) { | ||
digest = d | ||
}) | ||
} | ||
module.exports.metadata = putMetadata | ||
function putMetadata (cache, key, metadata, opts, cb) { | ||
if (!cb) { | ||
cb = opts | ||
opts = null | ||
} | ||
opts = Object.create(opts || {}) | ||
opts.metadata = metadata | ||
index.find(cache, key, function (err, info) { | ||
if (err) { return cb(err) } | ||
if (!info) { return cb(index.notFoundError(cache, key)) } | ||
index.insert(cache, key, info.digest, opts, cb) | ||
return to(function (chunk, enc, cb) { | ||
contentStream.write(chunk, enc, cb) | ||
}, function (cb) { | ||
index.insert(cache, key, digest, opts, cb) | ||
}) | ||
} |
131
README.md
@@ -1,2 +0,2 @@ | ||
# cacache [![npm version](https://img.shields.io/npm/v/cacache.svg)](https://npm.im/cacache) [![license](https://img.shields.io/npm/l/cacache.svg)](https://npm.im/cacache) [![Travis](https://img.shields.io/travis/zkat/cacache.svg)](https://travis-ci.org/zkat/cacache) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/zkat/cacache?svg=true)](https://ci.appveyor.com/project/zkat/cacache) | ||
# cacache [![npm version](https://img.shields.io/npm/v/cacache.svg)](https://npm.im/cacache) [![license](https://img.shields.io/npm/l/cacache.svg)](https://npm.im/cacache) [![Travis](https://img.shields.io/travis/zkat/cacache.svg)](https://travis-ci.org/zkat/cacache) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/zkat/cacache?svg=true)](https://ci.appveyor.com/project/zkat/cacache) [![Coverage Status](https://coveralls.io/repos/github/zkat/cacache/badge.svg?branch=latest)](https://coveralls.io/github/zkat/cacache?branch=latest) | ||
@@ -16,17 +16,7 @@ [`cacache`](https://github.com/zkat/cacache) is a Node.js library for managing | ||
* [Features](#features) | ||
* [Guide](#guide) | ||
* [Introduction](#introduction) | ||
* [Putting Data In](#insertion) | ||
* [Getting Data Out](#extraction) | ||
* [Querying the Cache](#queries) | ||
* [Cleaning Up](#cleanup) | ||
* [API](#api) | ||
* [`ls`](#ls) | ||
* [`get.directory`](#get-directory) | ||
* [`get.tarball`](#get-tarball) | ||
* [`get.stream`](#get-stream) | ||
* [`get.info`](#get-info) | ||
* [`put.file`](#put-file) | ||
* [`put.data`](#put-data) | ||
* [`put.stream`](#put-stream) | ||
* [`put.metadata`](#put-metadata) | ||
* [`put options`](#put-options) | ||
@@ -43,2 +33,3 @@ * [`rm.all`](#rm-all) | ||
const cacache = require('cacache') | ||
const fs = require('fs') | ||
@@ -51,6 +42,10 @@ const tarball = '/path/to/mytar.tgz' | ||
// Cache it! Use `cachePath` as the root of the content cache | ||
cacache.put.file(cachePath, key, tarball, (err, digest) => { | ||
if (err) { return console.error('Error saving your file!', err.code) } | ||
tarballDigest = digest // we'll use this later | ||
console.log(`Saved ${tarball} to ${cachePath} as ${digest}.`) | ||
fs.createReadStream( | ||
tarball | ||
).pipe( | ||
cacache.put.stream( | ||
cachePath, key | ||
).on('digest', (d) => tarballDigest = d) | ||
).on('end', function () { | ||
console.log(`Saved ${tarball} to ${cachePath}.`) | ||
}) | ||
@@ -61,11 +56,17 @@ | ||
// Copy the contents out of the cache and into their destination! | ||
cacache.get.file(cachePath, key, destination, (err) => { | ||
if (err) { return console.error('Error extracting data!', err.code) } | ||
console.log(`data extracted to ${cachePath}.`) | ||
cacache.get.stream( | ||
cachePath, key | ||
).pipe( | ||
fs.createWriteStream(destination) | ||
).on('end', () => { | ||
console.log('done extracting!') | ||
}) | ||
// The same thing, but skip the key index. | ||
cacache.get.file.byDigest(cachePath, tarballDigest, destination, (err) => { | ||
if (err) { return console.error('Error extracting data!', err.code) } | ||
console.log(`data extracted to ${cachePath}.`) | ||
cacache.get.stream.byDigest( | ||
cachePath, tarballDigest | ||
).pipe( | ||
fs.createWriteStream(destination) | ||
).on('end', () => { | ||
console.log('done extracting using sha1!') | ||
}) | ||
@@ -124,28 +125,4 @@ ``` | ||
#### <a name="get-file"></a> `> cacache.get.file(cache, key, destination, [opts], cb)` | ||
#### <a name="get-stream"></a> `> cacache.get.stream(cache, key, [opts])` | ||
Copies cached data identified by `key` to a file named `destination`. | ||
If there is no content identified by `key`, or if the locally-stored data does | ||
not pass the validity checksum, an error will be returned through the callback. | ||
A sub-function, `get.file.byDigest` may be used for identical behavior, | ||
except lookup will happen by content digest, bypassing the index entirely. | ||
##### Example | ||
```javascript | ||
cacache.get.file(cachePath, 'my-thing', './put/it/here', (err) => { | ||
if (err) { throw err } | ||
console.log(`my-thing contents copied to ./put/it/here`) | ||
}) | ||
cacache.get.file.byDigest(cachePath, pkg.sha, './put/it/here', (err) => { | ||
if (err) { throw err } | ||
console.log(`pkg contents copied to ./put/it/here`) | ||
}) | ||
``` | ||
#### <a name="get-stream"></a> `> cacache.get.stream(cache, key, [opts], cb)` | ||
Returns a stream of the cached data identified by `key`. | ||
@@ -210,5 +187,6 @@ | ||
#### <a name="put-file"></a> `> cacache.put.file(cache, key, file, [opts], cb)` | ||
#### <a name="put-stream"></a> `> cacache.put.stream(cache, key, stream, [opts])` | ||
Inserts a file into the cache by pathname. | ||
Inserts data from a stream into the cache. Emits a `digest` event with the | ||
digest of written contents when it succeeds. | ||
@@ -218,50 +196,11 @@ ##### Example | ||
```javascript | ||
cacache.put.file(cachePath, 'my-dotfiles', './tarball.tgz', (err, digest) => { | ||
if (err) { throw err } | ||
console.log(`Saved as ${digest}.`) | ||
}) | ||
request.get( | ||
'https://registry.npmjs.org/cacache/-/cacache-1.0.0.tgz' | ||
).pipe( | ||
cacache.put.stream( | ||
cachePath, 'registry.npmjs.org|cacache@1.0.0' | ||
).on('digest', d => console.log(`digest is ${d}`)) | ||
) | ||
``` | ||
#### <a name="put-data"></a> `> cacache.put.data(cache, key, filename, data, [opts], cb)` | ||
Inserts plain string data into the cache, using `filename` for the cache file. | ||
##### Example | ||
```javascript | ||
cacache.put.data(cachePath, key, filename, 'wompwomp', (err, digest) => { | ||
if (err) { throw err } | ||
console.log(`Wrote 'wompwomp' into cache. It will be in ${filename}`) | ||
}) | ||
``` | ||
#### <a name="put-stream"></a> `> cacache.put.stream(cache, key, stream, [opts], cb)` | ||
Inserts data from a stream into the cache. | ||
##### Example | ||
```javascript | ||
var req = request.get('https://registry.npmjs.org/cacache/-/cacache-1.0.0.tgz') | ||
cacache.put.stream(cachePath, 'registry.npmjs.org|cacache@1.0.0', req, (err, digest) => { | ||
if (err) { throw err } | ||
console.log(`Package tarball written to cache. sha: ${digest}`) | ||
}) | ||
``` | ||
#### <a name="put-metadata"></a> `> cacache.put.metadata(cache, key, metadata, [opts], cb)` | ||
Adds or updates metadata for a previously inserted entry. To add metadata on | ||
initial insertion, use `opts.metadata` in the other `cacache.put` functions. | ||
##### Example | ||
```javascript | ||
cacache.put.metadata(cachePath, 'registry.npmjs.org|cacache@1.0.0', { | ||
name: 'cacache', version: '1.0.0' | ||
}, (err, digest) => { | ||
if (err) { throw err } | ||
console.log(`Package tarball written to cache. sha: ${digest}`) | ||
}) | ||
``` | ||
#### <a name="put-options"></a> `> cacache.put options` | ||
@@ -290,3 +229,3 @@ | ||
Default: 'sha256' | ||
Default: 'sha1' | ||
@@ -293,0 +232,0 @@ Hashing algorithm to use when calculating the digest for inserted data. Can use |
30172
643
331