From 303ffc868266400a518602d2e9e9285361029cb2 Mon Sep 17 00:00:00 2001 From: scott Chacon Date: Mon, 19 Nov 2007 07:14:20 -0800 Subject: [PATCH] changed logging to be far more efficient if you're accessing all the commit objects --- TODO | 3 +-- benchmark.rb | 8 ++++---- camping/gitweb.rb | 4 ++-- lib/git/lib.rb | 46 +++++++++++++++++++++++++++++++++++++++++----- lib/git/log.rb | 4 ++-- lib/git/object.rb | 21 ++++++++++++++++----- tests/units/test_lib.rb | 3 +++ 7 files changed, 69 insertions(+), 20 deletions(-) diff --git a/TODO b/TODO index a0fa7ba..dc8cde5 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,7 @@ * more documentation +* logging (Git.open(:log => Logger.new)) -* more low level index actions - - (with_index), checkout-index, read-tree, write-tree, update-ref * git revert, stash, rebase diff --git a/benchmark.rb b/benchmark.rb index 58e9703..e5a8953 100644 --- a/benchmark.rb +++ b/benchmark.rb @@ -2,8 +2,8 @@ require 'fileutils' require 'benchmark' require 'rubygems' require 'ruby-prof' -#require_gem 'git', '1.0.3' -require 'lib/git' +require_gem 'git', '1.0.3' +#require 'lib/git' def main @wbare = File.expand_path(File.join('tests', 'files', 'working.git')) @@ -66,8 +66,8 @@ def main log.size log.size log.first - g.log.between('v2.5').object('example.txt').size - g.log.since("2 years ago").size + g.log.between('v2.5').object('example.txt').map { |c| c.message } + g.log.since("2 years ago").map { |c| c.message } end end diff --git a/camping/gitweb.rb b/camping/gitweb.rb index 6322e17..8ecb0e6 100644 --- a/camping/gitweb.rb +++ b/camping/gitweb.rb @@ -142,7 +142,7 @@ module GitWeb::Controllers @git = Git.bare(@repo.path) @tree1 = tree1 @tree2 = tree2 - @diff = @git.diff(tree1, tree2) + @diff = @git.diff(tree2, tree1) render :diff end end @@ -255,7 +255,7 @@ module GitWeb::Views @commit.parents.each do |p| code { a p.sha, :href => R(Commit, @repo, p.sha) } span.space ' ' - a 'diff', :href => R(DiffTwo, @repo, p.sha, @commit.sha) + a 'diff', :href => R(Diff, @repo, p.sha, @commit.sha) span.space ' ' a 'archive', :href => R(Archive, @repo, p.gtree.sha) br diff --git a/lib/git/lib.rb b/lib/git/lib.rb index 31cf164..0d44183 100644 --- a/lib/git/lib.rb +++ b/lib/git/lib.rb @@ -69,6 +69,18 @@ module Git command_lines('log', arr_opts, true).map { |l| l.split.first } end + def full_log_commits(opts = {}) + arr_opts = ['--pretty=raw'] + arr_opts << "-#{opts[:count]}" if opts[:count] + arr_opts << "--since=\"#{opts[:since]}\"" if opts[:since].is_a? String + arr_opts << "#{opts[:between][0].to_s}..#{opts[:between][1].to_s}" if (opts[:between] && opts[:between].size == 2) + arr_opts << opts[:object] if opts[:object].is_a? String + arr_opts << '-- ' + opts[:path_limiter] if opts[:path_limiter].is_a? String + + full_log = command_lines('log', arr_opts, true) + process_commit_data(full_log) + end + def revparse(string) command('rev-parse', string) end @@ -87,28 +99,52 @@ module Git # returns useful array of raw commit object data def commit_data(sha) + sha = sha.to_s + cdata = command_lines('cat-file', ['commit', sha]) + process_commit_data(cdata, sha) + end + + def process_commit_data(data, sha = nil) in_message = false - hsh = {'message' => '', 'parent' => []} - command_lines('cat-file', ['commit', sha.to_s]).each do |line| - if in_message + if sha + hsh = {'sha' => sha, 'message' => '', 'parent' => []} + else + hsh_array = [] + end + + data.each do |line| + if in_message && line != '' hsh['message'] += line + "\n" end - + if (line != '') && !in_message data = line.split key = data.shift value = data.join(' ') + if key == 'commit' + sha = value + hsh_array << hsh if hsh + hsh = {'sha' => sha, 'message' => '', 'parent' => []} + end if key == 'parent' hsh[key] << value else hsh[key] = value end + elsif in_message && line == '' + in_message = false else in_message = true end end - hsh + + if hsh_array + hsh_array << hsh if hsh + hsh_array + else + hsh + end end def object_contents(sha) diff --git a/lib/git/log.rb b/lib/git/log.rb index c91538d..9437ea6 100644 --- a/lib/git/log.rb +++ b/lib/git/log.rb @@ -84,9 +84,9 @@ module Git # actually run the 'git log' command def run_log - log = @base.lib.log_commits(:count => @count, :object => @object, + log = @base.lib.full_log_commits(:count => @count, :object => @object, :path_limiter => @path, :since => @since, :between => @between) - @commits = log.map { |l| Git::Object::Commit.new(@base, l) } + @commits = log.map { |c| Git::Object::Commit.new(@base, c['sha'], c) } end end diff --git a/lib/git/object.rb b/lib/git/object.rb index aeeae89..058053c 100644 --- a/lib/git/object.rb +++ b/lib/git/object.rb @@ -151,6 +151,13 @@ module Git @committer = nil @message = nil + def initialize(base, sha, init = nil) + super(base, sha) + if init + set_commit(init) + end + end + def message check_commit @message @@ -199,6 +206,14 @@ module Git def diff_parent diff(parent) end + + def set_commit(data) + @committer = Git::Author.new(data['committer']) + @author = Git::Author.new(data['author']) + @tree = Tree.new(@base, data['tree']) + @parents = data['parent'].map{ |sha| Commit.new(@base, sha) } + @message = data['message'].chomp + end private @@ -210,11 +225,7 @@ module Git def check_commit if !@tree data = @base.lib.commit_data(@objectish) - @committer = Git::Author.new(data['committer']) - @author = Git::Author.new(data['author']) - @tree = Tree.new(@base, data['tree']) - @parents = data['parent'].map{ |sha| Commit.new(@base, sha) } - @message = data['message'].chomp + set_commit(data) end end diff --git a/tests/units/test_lib.rb b/tests/units/test_lib.rb index 9a3479b..f9170e6 100644 --- a/tests/units/test_lib.rb +++ b/tests/units/test_lib.rb @@ -44,6 +44,9 @@ class TestLib < Test::Unit::TestCase a = @lib.log_commits :count => 20, :path_limiter => 'ex_dir/' assert_equal(1, a.size) + + a = @lib.full_log_commits :count => 20 + assert_equal(20, a.size) end def test_revparse -- 2.11.4.GIT