From 06e335a875283cc3fded656c0f7f6b4c95bad5a1 Mon Sep 17 00:00:00 2001 From: Wil Chung Date: Wed, 5 Mar 2014 18:25:47 -0800 Subject: [PATCH] can stream blob data --- src/blob.coffee | 16 ++++++++++++++++ src/git.coffee | 15 ++++++++++++++- test/blob.test.coffee | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/blob.coffee b/src/blob.coffee index 2f1d634..7965a7e 100644 --- a/src/blob.coffee +++ b/src/blob.coffee @@ -8,10 +8,26 @@ module.exports = class Blob # # callback - Receives `(err, data)`. # + # Warning, this only returns files less than 200k, the standard buffer size for + # node's exec(). If you need to get bigger files, you should use dataStream() to + # get a stream for the file's data + # data: (callback) -> @repo.git "cat-file", {p: true}, @id , (err, stdout, stderr) -> return callback err, stdout + # Public: Get the blob contents as a stream + # + # returns - [dataStream, errstream] + # + # Usage: + # [blobstream, _] = blob.dataStream() + # blobstream.pipe(res) + # + dataStream: () -> + streams = @repo.git.streamCmd "cat-file", {p: true}, [@id] + return streams + toString: -> "#" diff --git a/src/git.coffee b/src/git.coffee index 22e9dec..eded6ac 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -1,5 +1,5 @@ fs = require 'fs' -{exec} = require 'child_process' +{exec, spawn} = require 'child_process' module.exports = Git = (git_dir, dot_git) -> dot_git ||= "#{git_dir}/.git" @@ -21,6 +21,19 @@ module.exports = Git = (git_dir, dot_git) -> git.cmd = (command, options, args, callback) -> git command, options, args, callback + # Public: stream results of git command + # + # This is used for large files that you'd need to stream. + # + # returns [outstream, errstream] + # + git.streamCmd = (command, options, args) -> + options ?= {} + options = options_to_argv options + args ?= [] + allargs = [command].concat(options).concat(args) + process = spawn Git.bin, allargs, {cwd: git_dir, encoding: 'binary'} + return [process.stdout, process.stderr] # Public: Get a list of the remote names. # diff --git a/test/blob.test.coffee b/test/blob.test.coffee index 0183165..01d5d34 100644 --- a/test/blob.test.coffee +++ b/test/blob.test.coffee @@ -43,3 +43,36 @@ describe "Blob", -> data.should.be.type "string" data.should.include "!!!" + describe "#dataStream", -> + describe "of a file off the root", -> + repo = git "#{__dirname}/fixtures/branched" + data = "" + before (done) -> + repo.tree().blobs (err, blobs) -> + [dataStream, _] = blobs[0].dataStream() + dataStream.on 'data', (buf) -> + data += buf.toString() + .on 'end', -> + done() + + it "is a string", -> + data.should.be.type "string" + data.should.include "Bla" + + describe "of a file in a subdir", -> + repo = git "#{__dirname}/fixtures/branched" + data = "" + before (done) -> + repo.tree().trees (err, trees) -> + trees[0].blobs (err, blobs) -> + [dataStream, _] = blobs[0].dataStream() + dataStream.on 'data', (buf) -> + data += buf.toString() + .on 'end', -> + done() + + it "is a string", -> + data.should.be.type "string" + data.should.include "!!!" + +