summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/git/lib.rb20
-rw-r--r--lib/git/object.rb14
-rw-r--r--tests/units/test_lib.rb27
-rw-r--r--tests/units/test_object.rb9
4 files changed, 61 insertions, 9 deletions
diff --git a/lib/git/lib.rb b/lib/git/lib.rb
index 55191fe..033df12 100644
--- a/lib/git/lib.rb
+++ b/lib/git/lib.rb
@@ -166,8 +166,8 @@ module Git
end
end
- def object_contents(sha)
- command('cat-file', ['-p', sha])
+ def object_contents(sha, &block)
+ command('cat-file', ['-p', sha], &block)
end
def ls_tree(sha)
@@ -596,20 +596,20 @@ module Git
command(cmd, opts, chdir).split("\n")
end
- def command(cmd, opts = [], chdir = true)
+ def command(cmd, opts = [], chdir = true, &block)
ENV['GIT_DIR'] = @git_dir if (@git_dir != ENV['GIT_DIR'])
ENV['GIT_INDEX_FILE'] = @git_index_file if (@git_index_file != ENV['GIT_INDEX_FILE'])
ENV['GIT_WORK_TREE'] = @git_work_dir if (@git_work_dir != ENV['GIT_WORK_TREE'])
path = @git_work_dir || @git_dir || @path
opts = opts.to_a.join(' ')
- git_cmd = "git #{cmd} #{opts}"
+ git_cmd = "git #{cmd} #{opts} 2>&1"
out = nil
if chdir && (Dir.getwd != path)
- Dir.chdir(path) { out = `#{git_cmd} 2>&1`.chomp }
+ Dir.chdir(path) { out = run_command(git_cmd, &block) }
else
- out = `#{git_cmd} 2>&1`.chomp
+ out = run_command(git_cmd, &block)
end
if @logger
@@ -626,5 +626,13 @@ module Git
out
end
+ def run_command(git_cmd, &block)
+ if block_given?
+ IO.popen(git_cmd, &block)
+ else
+ `#{git_cmd}`.chomp
+ end
+ end
+
end
end
diff --git a/lib/git/object.rb b/lib/git/object.rb
index e35060c..5ec24e2 100644
--- a/lib/git/object.rb
+++ b/lib/git/object.rb
@@ -28,9 +28,17 @@ module Git
@size || @size = @base.lib.object_size(@objectish)
end
- # caches the contents of this call in memory
- def contents
- @contents || @contents = @base.lib.object_contents(@objectish)
+ # get the object's contents
+ # if no block is given, the contents are cached in memory and returned as a string
+ # if a block is given, it yields an IO object (via IO::popen) which could be used to
+ # read a large file in chunks. use this for large files so that they are not held
+ # in memory
+ def contents(&block)
+ if block_given?
+ @base.lib.object_contents(@objectish, &block)
+ else
+ @contents || @contents = @base.lib.object_contents(@objectish)
+ end
end
def contents_array
diff --git a/tests/units/test_lib.rb b/tests/units/test_lib.rb
index 7cbbeef..59301f3 100644
--- a/tests/units/test_lib.rb
+++ b/tests/units/test_lib.rb
@@ -85,6 +85,33 @@ class TestLib < Test::Unit::TestCase
assert_equal(blob, @lib.object_contents('v2.5:example.txt')) #blob
end
+
+ def test_object_contents_with_block
+ commit = "tree 94c827875e2cadb8bc8d4cdd900f19aa9e8634c7\n"
+ commit += "parent 546bec6f8872efa41d5d97a369f669165ecda0de\n"
+ commit += "author scott Chacon <schacon@agadorsparticus.corp.reactrix.com> 1194561188 -0800\n"
+ commit += "committer scott Chacon <schacon@agadorsparticus.corp.reactrix.com> 1194561188 -0800\n"
+ commit += "\ntest"
+
+ @lib.object_contents('1cc8667014381') do |f|
+ assert_equal(commit, f.read.chomp)
+ end
+
+ # commit
+
+ tree = "040000 tree 6b790ddc5eab30f18cabdd0513e8f8dac0d2d3ed\tex_dir\n"
+ tree += "100644 blob 3aac4b445017a8fc07502670ec2dbf744213dd48\texample.txt"
+
+ @lib.object_contents('1cc8667014381^{tree}') do |f|
+ assert_equal(tree, f.read.chomp) #tree
+ end
+
+ blob = "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n2"
+
+ @lib.object_contents('v2.5:example.txt') do |f|
+ assert_equal(blob, f.read.chomp) #blob
+ end
+ end
# returns Git::Branch object array
def test_branches_all
diff --git a/tests/units/test_object.rb b/tests/units/test_object.rb
index 543f021..427992b 100644
--- a/tests/units/test_object.rb
+++ b/tests/units/test_object.rb
@@ -102,6 +102,15 @@ class TestObject < Test::Unit::TestCase
o = @git.gblob('v2.6:example.txt')
assert_equal('replace with new text', o.contents)
assert_equal('replace with new text', o.contents) # this should be cached
+
+ # make sure the block is called
+ block_called = false
+ o.contents do |f|
+ block_called = true
+ assert_equal('replace with new text', f.read.chomp)
+ end
+
+ assert(block_called)
end
def test_revparse