diff options
-rw-r--r-- | lib/git/lib.rb | 20 | ||||
-rw-r--r-- | lib/git/object.rb | 14 | ||||
-rw-r--r-- | tests/units/test_lib.rb | 27 | ||||
-rw-r--r-- | tests/units/test_object.rb | 9 |
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 |