diff --git a/lib/git_stats/git_data/blob.rb b/lib/git_stats/git_data/blob.rb index 94db7ac93..f0ef85ba9 100644 --- a/lib/git_stats/git_data/blob.rb +++ b/lib/git_stats/git_data/blob.rb @@ -5,14 +5,14 @@ module GitStats class Blob include HashInitializable - attr_reader :repo, :hash, :filename + attr_reader :repo, :sha, :filename def lines_count - @lines_count ||= binary? ? 0 : repo.run("git cat-file blob #{self.hash} | wc -l").to_i + @lines_count ||= binary? ? 0 : repo.run("git cat-file blob #{self.sha} | wc -l").to_i end def content - @content ||= repo.run("git cat-file blob #{self.hash}") + @content ||= repo.run("git cat-file blob #{self.sha}") end def extension @@ -20,15 +20,15 @@ module GitStats end def binary? - repo.run("git cat-file blob #{self.hash} | grep -m 1 '^'") =~ /Binary file/ + repo.run("git cat-file blob #{self.sha} | grep -m 1 '^'") =~ /Binary file/ end def to_s - "#{self.class} #@hash #@filename" + "#{self.class} #@sha #@filename" end def ==(other) - [self.repo, self.hash, self.filename] == [other.repo, other.hash, other.filename] + [self.repo, self.sha, self.filename] == [other.repo, other.sha, other.filename] end end diff --git a/lib/git_stats/git_data/command_parser.rb b/lib/git_stats/git_data/command_parser.rb index a2dd64100..d0c410895 100644 --- a/lib/git_stats/git_data/command_parser.rb +++ b/lib/git_stats/git_data/command_parser.rb @@ -15,15 +15,15 @@ module GitStats def parse_ls_tree(result, params) result.lines.map do |line| - mode, type, hash, filename = line.scan(/(.*) (.*) (.*)\t(.*)/).first.map(&:strip) - {mode: mode, type: type, hash: hash, filename: filename} + mode, type, sha, filename = line.scan(/(.*) (.*) (.*)\t(.*)/).first.map(&:strip) + {mode: mode, type: type, sha: sha, filename: filename} end end def parse_rev_list(result, params) result.lines.map do |line| - hash, stamp, date, author_email = line.split('|').map(&:strip) - {hash: hash, stamp: stamp, date: date, author_email: author_email} + sha, stamp, date, author_email = line.split('|').map(&:strip) + {sha: sha, stamp: stamp, date: date, author_email: author_email} end end diff --git a/lib/git_stats/git_data/commit.rb b/lib/git_stats/git_data/commit.rb index 024691ee4..7ffa7abcc 100644 --- a/lib/git_stats/git_data/commit.rb +++ b/lib/git_stats/git_data/commit.rb @@ -5,14 +5,22 @@ module GitStats class Commit include HashInitializable - attr_reader :repo, :hash, :stamp, :date, :author + attr_reader :repo, :sha, :stamp, :date, :author def files - @files ||= repo.run_and_parse("git ls-tree -r #{self.hash}").map do |file| - Blob.new(repo: repo, filename: file[:filename], hash: file[:hash]) + @files ||= repo.run_and_parse("git ls-tree -r #{self.sha}").map do |file| + Blob.new(repo: repo, filename: file[:filename], sha: file[:sha]) end.extend(ByFieldFinder) end + def binary_files + @binary_files ||= files.select { |f| f.binary? } + end + + def text_files + @text_files ||= files - binary_files + end + def files_by_extension @files_by_extension ||= files.inject({}) { |acc, f| acc[f.extension] ||= []; acc[f.extension] << f; acc } end @@ -28,19 +36,11 @@ module GitStats end def files_count - @files_count ||= repo.run("git ls-tree -r --name-only #{self.hash} | wc -l").to_i - end - - def binary_files_count - files.find_all { |f| f.binary? }.size - end - - def text_files_count - files_count - binary_files_count + @files_count ||= repo.run("git ls-tree -r --name-only #{self.sha} | wc -l").to_i end def lines_count - @lines_count ||= repo.run("git diff --shortstat `git hash-object -t tree /dev/null` #{self.hash}").lines.map do |line| + @lines_count ||= repo.run("git diff --shortstat `git hash-object -t tree /dev/null` #{self.sha}").lines.map do |line| line[/(\d+) insertions?/, 1].to_i end.sum end @@ -50,12 +50,12 @@ module GitStats end def to_s - "#{self.class} #@hash" + "#{self.class} #@sha" end def ==(other) - [self.repo, self.hash, self.stamp, self.date, self.author] == - [other.repo, other.hash, other.stamp, other.date, other.author] + [self.repo, self.sha, self.stamp, self.date, self.author] == + [other.repo, other.sha, other.stamp, other.date, other.author] end end end diff --git a/lib/git_stats/git_data/repo.rb b/lib/git_stats/git_data/repo.rb index 4a1ef5b93..c800f6b21 100644 --- a/lib/git_stats/git_data/repo.rb +++ b/lib/git_stats/git_data/repo.rb @@ -8,7 +8,7 @@ module GitStats attr_reader :path delegate :files, :files_by_extension, :files_by_extension_count, :lines_by_extension, - :files_count, :binary_files_count, :text_files_count, :lines_count, to: :last_commit + :files_count, :binary_files, :text_files, :lines_count, to: :last_commit def initialize(params) super(params) @@ -25,7 +25,7 @@ module GitStats @commits ||= run_and_parse("git rev-list --pretty=format:'%h|%at|%ai|%aE' #{commit_range} | grep -v commit").map do |commit_line| Commit.new( repo: self, - hash: commit_line[:hash], + sha: commit_line[:sha], stamp: commit_line[:stamp], date: DateTime.parse(commit_line[:date]), author: authors.by_email(commit_line[:author_email]) @@ -74,11 +74,11 @@ module GitStats end def commit_range - @first_commit_hash ? "#@first_commit_hash..#{last_commit_hash}" : last_commit_hash + @first_commit_sha ? "#@first_commit_sha..#{last_commit_sha}" : last_commit_sha end - def last_commit_hash - @last_commit_hash ||= 'HEAD' + def last_commit_sha + @last_commit_sha ||= 'HEAD' end def short_stats diff --git a/lib/git_stats/git_data/short_stat.rb b/lib/git_stats/git_data/short_stat.rb index 5b5efea9e..ceb4cb799 100644 --- a/lib/git_stats/git_data/short_stat.rb +++ b/lib/git_stats/git_data/short_stat.rb @@ -14,7 +14,7 @@ module GitStats private def calculate_stat - stat_line = commit.repo.run("git show --shortstat --oneline #{commit.hash}").lines.to_a[1] + stat_line = commit.repo.run("git show --shortstat --oneline #{commit.sha}").lines.to_a[1] if stat_line.blank? @files_changed = @insertions = @deletions = 0 else diff --git a/spec/factories.rb b/spec/factories.rb index c7a9cd5e1..eb339df5f 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -15,7 +15,7 @@ FactoryGirl.define do end factory :commit, class: GitStats::GitData::Commit do - sequence(:hash) { |i| i } + sequence(:sha) { |i| i } sequence(:stamp) { |i| i } sequence(:date) { |i| Date.new(i) } association :repo, strategy: :build diff --git a/spec/git_data/author_spec.rb b/spec/git_data/author_spec.rb index 77a430086..e8de1ae94 100644 --- a/spec/git_data/author_spec.rb +++ b/spec/git_data/author_spec.rb @@ -4,8 +4,8 @@ describe GitStats::GitData::Author do let(:repo) { build(:repo) } let(:author) { build(:author, repo: repo) } let(:other_author) { build(:author, repo: repo) } - let(:my_commits) { 10.times.map { |i| double("my_commit #{i}", :author => author) } } - let(:other_commits) { 10.times.map { |i| double("other_commit #{i}", :author => other_author) } } + let(:my_commits) { 10.times.map { |i| double("my_commit #{i}", author: author, short_stat: double("my_short_stat #{i}", insertions: 5, deletions: 10)) } } + let(:other_commits) { 10.times.map { |i| double("other_commit #{i}", author: other_author) } } before { repo.stub(:commits => my_commits + other_commits) } @@ -13,5 +13,12 @@ describe GitStats::GitData::Author do author.commits.should == my_commits end + it 'should count lines added from short stat' do + author.lines_added.should == 50 + end + + it 'should count lines deleted from short stat' do + author.lines_deleted.should == 100 + end end \ No newline at end of file diff --git a/spec/git_data/blob_spec.rb b/spec/git_data/blob_spec.rb index 47c678a9b..af7497f4d 100644 --- a/spec/git_data/blob_spec.rb +++ b/spec/git_data/blob_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' describe GitStats::GitData::Blob do let(:repo) { double } - let(:png_blob) { GitStats::GitData::Blob.new(filename: 'abc.png', hash: 'hash_png', repo: repo) } - let(:txt_blob) { GitStats::GitData::Blob.new(filename: 'abc.txt', hash: 'hash_txt', repo: repo) } + let(:png_blob) { GitStats::GitData::Blob.new(filename: 'abc.png', sha: 'hash_png', repo: repo) } + let(:txt_blob) { GitStats::GitData::Blob.new(filename: 'abc.txt', sha: 'hash_txt', repo: repo) } it 'should return 0 as lines count when files is binary' do png_blob.should_receive(:binary?).and_return true diff --git a/spec/git_data/commit_range_spec.rb b/spec/git_data/commit_range_spec.rb index b7e64971e..958a4b813 100644 --- a/spec/git_data/commit_range_spec.rb +++ b/spec/git_data/commit_range_spec.rb @@ -9,22 +9,22 @@ describe GitStats::GitData::Repo do end it 'should return last_commit if it was given' do - repo = build(:repo, last_commit_hash: 'abc') + repo = build(:repo, last_commit_sha: 'abc') repo.commit_range.should == 'abc' end it 'should return range from first_commit to HEAD if first_commit was given' do - repo = build(:repo, first_commit_hash: 'abc') + repo = build(:repo, first_commit_sha: 'abc') repo.commit_range.should == 'abc..HEAD' end it 'should return range from first to last commit if both were given' do - repo = build(:repo, first_commit_hash: 'abc', last_commit_hash: 'def') + repo = build(:repo, first_commit_sha: 'abc', last_commit_sha: 'def') repo.commit_range.should == 'abc..def' end context 'git commands using range' do - let(:repo) { build(:repo, first_commit_hash: 'abc', last_commit_hash: 'def') } + let(:repo) { build(:repo, first_commit_sha: 'abc', last_commit_sha: 'def') } it 'should affect authors command' do repo.should_receive(:run).with('git shortlog -se abc..def').and_return("") diff --git a/spec/git_data/commit_spec.rb b/spec/git_data/commit_spec.rb index 16d7bac38..723be38ff 100644 --- a/spec/git_data/commit_spec.rb +++ b/spec/git_data/commit_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe GitStats::GitData::Commit do - let(:commit) { build(:commit, hash: 'abc') } + let(:commit) { build(:commit, sha: 'abc') } describe 'git output parsing' do context 'parsing git ls-tree output' do @@ -14,26 +14,26 @@ describe GitStats::GitData::Commit do it 'should be parsed to files' do commit.files.should == [ - GitStats::GitData::Blob.new(repo: commit.repo, hash: "5ade7ad51a75ee7db4eb06cecd3918d38134087d", filename: "lib/git_stats/git_data/commit.rb"), - GitStats::GitData::Blob.new(repo: commit.repo, hash: "db01e94677a8f72289848e507a52a43de2ea109a", filename: "lib/git_stats/git_data/repo.rb"), - GitStats::GitData::Blob.new(repo: commit.repo, hash: "1463eacb3ac9f95f21f360f1eb935a84a9ee0895", filename: "templates/activity.haml"), - GitStats::GitData::Blob.new(repo: commit.repo, hash: "31d8b960a67f195bdedaaf9e7aa70b2389f3f1a8", filename: "templates/assets/bootstrap/css/bootstrap.min.css"), + GitStats::GitData::Blob.new(repo: commit.repo, sha: "5ade7ad51a75ee7db4eb06cecd3918d38134087d", filename: "lib/git_stats/git_data/commit.rb"), + GitStats::GitData::Blob.new(repo: commit.repo, sha: "db01e94677a8f72289848e507a52a43de2ea109a", filename: "lib/git_stats/git_data/repo.rb"), + GitStats::GitData::Blob.new(repo: commit.repo, sha: "1463eacb3ac9f95f21f360f1eb935a84a9ee0895", filename: "templates/activity.haml"), + GitStats::GitData::Blob.new(repo: commit.repo, sha: "31d8b960a67f195bdedaaf9e7aa70b2389f3f1a8", filename: "templates/assets/bootstrap/css/bootstrap.min.css"), ] end it 'should group files by extension' do commit.files_by_extension.should == {'.rb' => [ - GitStats::GitData::Blob.new(repo: commit.repo, hash: "5ade7ad51a75ee7db4eb06cecd3918d38134087d", filename: "lib/git_stats/git_data/commit.rb"), - GitStats::GitData::Blob.new(repo: commit.repo, hash: "db01e94677a8f72289848e507a52a43de2ea109a", filename: "lib/git_stats/git_data/repo.rb") + GitStats::GitData::Blob.new(repo: commit.repo, sha: "5ade7ad51a75ee7db4eb06cecd3918d38134087d", filename: "lib/git_stats/git_data/commit.rb"), + GitStats::GitData::Blob.new(repo: commit.repo, sha: "db01e94677a8f72289848e507a52a43de2ea109a", filename: "lib/git_stats/git_data/repo.rb") ], '.haml' => [ - GitStats::GitData::Blob.new(repo: commit.repo, hash: "1463eacb3ac9f95f21f360f1eb935a84a9ee0895", filename: "templates/activity.haml") + GitStats::GitData::Blob.new(repo: commit.repo, sha: "1463eacb3ac9f95f21f360f1eb935a84a9ee0895", filename: "templates/activity.haml") ], '.css' => [ - GitStats::GitData::Blob.new(repo: commit.repo, hash: "31d8b960a67f195bdedaaf9e7aa70b2389f3f1a8", filename: "templates/assets/bootstrap/css/bootstrap.min.css") + GitStats::GitData::Blob.new(repo: commit.repo, sha: "31d8b960a67f195bdedaaf9e7aa70b2389f3f1a8", filename: "templates/assets/bootstrap/css/bootstrap.min.css") ] } end - it 'should count lines by extension' do + it 'should count lines by extension excluding empty or binary files' do GitStats::GitData::Blob.should_receive(:new).and_return( double(lines_count: 40, extension: '.rb'), double(lines_count: 60, extension: '.rb'), diff --git a/spec/git_data/repo_spec.rb b/spec/git_data/repo_spec.rb index c184f7432..268dd0da9 100644 --- a/spec/git_data/repo_spec.rb +++ b/spec/git_data/repo_spec.rb @@ -26,13 +26,13 @@ ce34874|1347482927|2012-09-12 22:48:47 +0200|joe.doe@gmail.com repo.commits.should == [ GitStats::GitData::Commit.new( - repo: repo, hash: "5eab339", stamp: "1345835073", date: DateTime.parse("2012-08-24 21:04:33 +0200"), + repo: repo, sha: "5eab339", stamp: "1345835073", date: DateTime.parse("2012-08-24 21:04:33 +0200"), author: repo.authors.by_email("john.doe@gmail.com")), GitStats::GitData::Commit.new( - repo: repo, hash: "ce34874", stamp: "1347482927", date: DateTime.parse("2012-09-12 22:48:47 +0200"), + repo: repo, sha: "ce34874", stamp: "1347482927", date: DateTime.parse("2012-09-12 22:48:47 +0200"), author: repo.authors.by_email("joe.doe@gmail.com")), GitStats::GitData::Commit.new( - repo: repo, hash: "e4412c3", stamp: "1348603824", date: DateTime.parse("2012-09-25 22:10:24 +0200"), + repo: repo, sha: "e4412c3", stamp: "1348603824", date: DateTime.parse("2012-09-25 22:10:24 +0200"), author: repo.authors.by_email("john.doe@gmail.com")) ] end diff --git a/spec/git_data/short_stat_spec.rb b/spec/git_data/short_stat_spec.rb index 1a4917bc5..d19a3ecf2 100644 --- a/spec/git_data/short_stat_spec.rb +++ b/spec/git_data/short_stat_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe GitStats::GitData::ShortStat do - let(:commit) { build(:commit, hash: 'abc') } + let(:commit) { build(:commit, sha: 'abc') } describe 'git output parsing' do context 'parsing git show output' do diff --git a/spec/integration/author_spec.rb b/spec/integration/author_spec.rb index e33070c66..29afdefd7 100644 --- a/spec/integration/author_spec.rb +++ b/spec/integration/author_spec.rb @@ -7,8 +7,8 @@ describe GitStats::GitData::Activity do let(:jd) { repo.authors.by_email('john.doe@gmail.com') } it 'should filter commits to author' do - tg.commits.map(&:hash).should =~ %w(b3b4f81 d60b5ec ab47ef8 2c11f5e c87ecf9 b621a5d 4e7d0e9 872955c) - jd.commits.map(&:hash).should =~ %w(fd66657 81e8bef) + tg.commits.map(&:sha).should =~ %w(b3b4f81 d60b5ec ab47ef8 2c11f5e c87ecf9 b621a5d 4e7d0e9 872955c) + jd.commits.map(&:sha).should =~ %w(fd66657 81e8bef) end context 'activity' do diff --git a/spec/integration/file_spec.rb b/spec/integration/file_spec.rb index 9db6127e5..34c5e0681 100644 --- a/spec/integration/file_spec.rb +++ b/spec/integration/file_spec.rb @@ -8,7 +8,7 @@ describe GitStats::GitData::Repo do end it 'should retrieve correct file content for old file' do - repo.commits.by_hash('c87ecf9').files.by_filename('test.txt').content.should == "bb + repo.commits.by_sha('c87ecf9').files.by_filename('test.txt').content.should == "bb diff --git a/spec/integration/repo_spec.rb b/spec/integration/repo_spec.rb index 56310e253..c61935363 100644 --- a/spec/integration/repo_spec.rb +++ b/spec/integration/repo_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe GitStats::GitData::Repo do - let(:repo) { build(:test_repo, last_commit_hash: '872955c') } + let(:repo) { build(:test_repo, last_commit_sha: '872955c') } it 'should gather all authors' do repo.authors.should =~ [ @@ -15,7 +15,7 @@ describe GitStats::GitData::Repo do end it 'should gather all commits sorted by date' do - repo.commits.map(&:hash).should =~ %w(b3b4f81 d60b5ec ab47ef8 2c11f5e c87ecf9 b621a5d fd66657 81e8bef 4e7d0e9 872955c) + repo.commits.map(&:sha).should =~ %w(b3b4f81 d60b5ec ab47ef8 2c11f5e c87ecf9 b621a5d fd66657 81e8bef 4e7d0e9 872955c) end it 'should return project name from dir' do diff --git a/spec/stats_view/charts/repo_charts_spec.rb b/spec/stats_view/charts/repo_charts_spec.rb index b2328589e..584dc7ced 100644 --- a/spec/stats_view/charts/repo_charts_spec.rb +++ b/spec/stats_view/charts/repo_charts_spec.rb @@ -1,16 +1,27 @@ require 'spec_helper' +shared_examples_for "column_chart" do + it 'should be a column chart' do + chart.should be_a GitStats::StatsView::Charts::Chart + chart.options[:chart][:type].should == "column" + end +end + +shared_examples_for "datetime_chart" do + it 'should be a datetime chart' do + chart.should be_a GitStats::StatsView::Charts::Chart + chart.options[:xAxis][:type].should == "datetime" + end +end + describe GitStats::StatsView::Charts::RepoCharts do let(:charts) { GitStats::StatsView::Charts::All.new(repo) } context 'files_by_extension chart' do let(:repo) { double(files_by_extension_count: {'.rb' => 5, '.txt' => 3}) } - let(:chart) { charts.repo_charts.files_by_extension } + let(:chart) { charts.files_by_extension } - it 'should be a column chart' do - chart.should be_a GitStats::StatsView::Charts::Chart - chart.options[:chart][:type].should == "column" - end + it_behaves_like "column_chart" it 'should have 1 data series with files_by_extension_count' do chart.should have(1).data @@ -21,12 +32,9 @@ describe GitStats::StatsView::Charts::RepoCharts do context 'lines_by_extension chart' do let(:repo) { double(lines_by_extension: {'.rb' => 50, '.txt' => 30}) } - let(:chart) { charts.repo_charts.lines_by_extension } + let(:chart) { charts.lines_by_extension } - it 'should be a column chart' do - chart.should be_a GitStats::StatsView::Charts::Chart - chart.options[:chart][:type].should == "column" - end + it_behaves_like "column_chart" it 'should have 1 data series with lines_by_extension' do chart.should have(1).data @@ -37,12 +45,9 @@ describe GitStats::StatsView::Charts::RepoCharts do context 'files_by_date chart' do let(:repo) { double(commits: [double(date: 5)], files_count_each_day: [10, 15, 12, 20]) } - let(:chart) { charts.repo_charts.files_by_date } + let(:chart) { charts.files_by_date } - it 'should be a datetime chart' do - chart.should be_a GitStats::StatsView::Charts::Chart - chart.options[:chart][:type].should == "datetime" - end + it_behaves_like "datetime_chart" it 'should have 1 data series with files_by_date' do chart.should have(1).data @@ -53,12 +58,9 @@ describe GitStats::StatsView::Charts::RepoCharts do context 'lines_by_date chart' do let(:repo) { double(commits: [double(date: 6)], lines_count_each_day: [100, 150, 120, 200]) } - let(:chart) { charts.repo_charts.lines_by_date } + let(:chart) { charts.lines_by_date } - it 'should be a datetime chart' do - chart.should be_a GitStats::StatsView::Charts::Chart - chart.options[:chart][:type].should == "datetime" - end + it_behaves_like "datetime_chart" it 'should have 1 data series with lines_by_date' do chart.should have(1).data @@ -66,4 +68,30 @@ describe GitStats::StatsView::Charts::RepoCharts do chart.data[0][:pointStart].should == 6000 end end + + context 'lines_added_by_author chart' do + let(:repo) { double(commits: [double(date: 6)], lines_added_by_author: {double(email: 'author1') => 50, double(email: 'author2') => 30}) } + let(:chart) { charts.lines_added_by_author } + + it_behaves_like "column_chart" + + it 'should have 1 data series with lines_added_by_author' do + chart.should have(1).data + chart.options[:xAxis][:categories].should == %w(author1 author2) + chart.data[0][:data].should == [50, 30] + end + end + + context 'lines_deleted_by_author chart' do + let(:repo) { double(commits: [double(date: 6)], lines_deleted_by_author: {double(email: 'author1') => 30, double(email: 'author2') => 50}) } + let(:chart) { charts.lines_deleted_by_author } + + it_behaves_like "column_chart" + + it 'should have 1 data series with lines_deleted_by_author' do + chart.should have(1).data + chart.options[:xAxis][:categories].should == %w(author1 author2) + chart.data[0][:data].should == [30, 50] + end + end end \ No newline at end of file diff --git a/templates/index.haml b/templates/index.haml index 57cca42a5..6dcc8d27f 100644 --- a/templates/index.haml +++ b/templates/index.haml @@ -16,7 +16,7 @@ %td= repo.commits_period.map {|d| d.to_formatted_s(:long)}.join(" .. ") %tr %td= :total_files.t - %td= "#{repo.files_count} (binary: #{repo.binary_files_count}, text: #{repo.text_files_count})" + %td= "#{repo.files_count} (binary: #{repo.binary_files.size}, text: #{repo.text_files.size})" %tr %td= :total_lines.t %td= "#{repo.lines_count} lines (#{repo.short_stats.map(&:insertions).sum} insertions, #{repo.short_stats.map(&:deletions).sum} deletions)"