diff --git a/README.md b/README.md index 83336177e..241e16e72 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ It browses the repository and outputs html page with statistics. s, [--silent], [--no-silent] # Silent mode. Don't output anything. d, [--tree=TREE] # Tree where statistics should be generated. # Default: . + c, [--comment=COMMENT] # The string which is used for comments. + # Default: /// diff --git a/config/locales/de.yml b/config/locales/de.yml index b651fec25..59ae1ca1b 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -12,8 +12,10 @@ de: commits_by_hour: Commits in der Stunde files: Dateien lines: Zeilen + comments: Kommentare files_by_date: Dateien nach Datum lines_by_date: Zeilen nach Datum + comments_by_date: Kommentare nach Datum files_by_extension: Dateien nach Erweiterungen lines_by_extension: Zeilen nach Erweiterungen hour_of_day: Tagesstunden diff --git a/config/locales/en.yml b/config/locales/en.yml index 5b86ac490..e87850a06 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -13,8 +13,10 @@ en: commits_by_hour: Commits by hour files: Files lines: Lines + comments: Comments files_by_date: Files by date lines_by_date: Lines by date + comments_by_date: Comments by date files_by_extension: Files by extension lines_by_extension: Lines by extension hour_of_day: Hour of day diff --git a/lib/git_stats/base.rb b/lib/git_stats/base.rb index cdec51f05..3293c1166 100644 --- a/lib/git_stats/base.rb +++ b/lib/git_stats/base.rb @@ -18,6 +18,7 @@ require 'git_stats/git_data/command_runner' require 'git_stats/git_data/commit' require 'git_stats/git_data/repo' require 'git_stats/git_data/short_stat' +require 'git_stats/git_data/comment_stat' require 'git_stats/git_data/tree' require 'git_stats/stats_view/template' diff --git a/lib/git_stats/cli.rb b/lib/git_stats/cli.rb index ac317c6f9..bff4b5122 100644 --- a/lib/git_stats/cli.rb +++ b/lib/git_stats/cli.rb @@ -10,11 +10,12 @@ class GitStats::CLI < Thor option :to, :aliases => :t, :default => 'HEAD', :desc => 'Commit where statistics should stop.' option :silent, :aliases => :s, :type => :boolean, :desc => 'Silent mode. Don\'t output anything.' option :tree, :aliases => :d, :default => '.', :desc => 'Tree where statistics should be generated.' - + option :comment, :aliases => :c, :default => '///', :desc => 'The string which is used for comments.' + desc 'generate', 'Generates the statistics of a repository' def generate I18n.locale = options[:language] - GitStats::Generator.new(options[:path], options[:output], options[:from], options[:to], options[:tree]) { |g| + GitStats::Generator.new(options[:path], options[:output], options[:from], options[:to], options[:tree], options[:comment]) { |g| g.add_command_observer { |command, result| puts "#{command}" } unless options[:silent] }.render_all end diff --git a/lib/git_stats/generator.rb b/lib/git_stats/generator.rb index b3a87f03f..ec6949baa 100644 --- a/lib/git_stats/generator.rb +++ b/lib/git_stats/generator.rb @@ -4,10 +4,10 @@ module GitStats delegate :add_command_observer, to: :@repo delegate :render_all, to: :@view - def initialize(repo_path, out_path, first_commit_sha = nil, last_commit_sha = "HEAD", tree_path = ".") + def initialize(repo_path, out_path, first_commit_sha = nil, last_commit_sha = "HEAD", tree_path = ".", comment_string = "///") validate_repo_path(repo_path) - @repo = GitData::Repo.new(path: repo_path, first_commit_sha: first_commit_sha, last_commit_sha: last_commit_sha, tree_path: tree_path) + @repo = GitData::Repo.new(path: repo_path, first_commit_sha: first_commit_sha, last_commit_sha: last_commit_sha, tree_path: tree_path, comment_string: comment_string) view_data = StatsView::ViewData.new(@repo) @view = StatsView::View.new(view_data, out_path) diff --git a/lib/git_stats/git_data/comment_stat.rb b/lib/git_stats/git_data/comment_stat.rb new file mode 100644 index 000000000..0e2df709b --- /dev/null +++ b/lib/git_stats/git_data/comment_stat.rb @@ -0,0 +1,38 @@ +# -*- encoding : utf-8 -*- +module GitStats + module GitData + class CommentStat + attr_reader :commit, :insertions, :deletions + + def initialize(commit) + @commit = commit + calculate_stat + end + + def changed_lines + insertions + deletions + end + + def to_s + "#{self.class} #@commit" + end + + def escape_characters_in_string(string) + pattern = /(\'|\"|\.|\*|\/|\-|\\)/ + string.gsub(pattern){|match|"\\" + match} + end + + private + def calculate_stat + escaped_string = escape_characters_in_string(commit.repo.comment_string) + stat_line = commit.repo.run("git show #{commit.sha} | awk 'BEGIN {adds=0; dels=0} {if ($0 ~ /^\\+#{escaped_string}/) adds++; if ($0 ~ /^\-#{escaped_string}/) dels++} END {print adds \" insertions \" dels \" deletes\"}'").lines.to_a[0] + if stat_line.blank? + @insertions = @deletions = 0 + else + @insertions = stat_line[/(\d+) insertions?/, 1].to_i + @deletions = stat_line[/(\d+) deletes?/, 1].to_i + end + end + end + end +end diff --git a/lib/git_stats/git_data/commit.rb b/lib/git_stats/git_data/commit.rb index d8c6ee2db..0b574abd7 100644 --- a/lib/git_stats/git_data/commit.rb +++ b/lib/git_stats/git_data/commit.rb @@ -50,6 +50,10 @@ module GitStats @short_stat ||= ShortStat.new(self) end + def comment_stat + @comment_stat ||= CommentStat.new(self) + end + def to_s "#{self.class} #@sha" end diff --git a/lib/git_stats/git_data/repo.rb b/lib/git_stats/git_data/repo.rb index cf6011c89..e57aba9fa 100644 --- a/lib/git_stats/git_data/repo.rb +++ b/lib/git_stats/git_data/repo.rb @@ -6,10 +6,10 @@ module GitStats class Repo include HashInitializable - attr_reader :path, :first_commit_sha, :last_commit_sha, :tree_path + attr_reader :path, :first_commit_sha, :last_commit_sha, :tree_path, :comment_string delegate :files, :files_by_extension, :files_by_extension_count, :lines_by_extension, - :files_count, :binary_files, :text_files, :lines_count, to: :last_commit + :files_count, :binary_files, :text_files, :lines_count, :comments_count, to: :last_commit def initialize(params) super(params) @@ -64,6 +64,15 @@ module GitStats }] end + def comments_count_by_date + sum = 0 + @comment_count_each_day ||= Hash[commits.map { |commit| + sum += commit.comment_stat.insertions + sum -= commit.comment_stat.deletions + [commit.date.to_date, sum] + }].fill_empty_days!(aggregated: true) + end + def last_commit commits.last end @@ -80,6 +89,10 @@ module GitStats @short_stats ||= commits.map(&:short_stat) end + def comment_stats + @comment_stats ||= commits.map(&:comment_stat) + end + def activity @activity ||= Activity.new(commits) end diff --git a/lib/git_stats/stats_view/charts/charts.rb b/lib/git_stats/stats_view/charts/charts.rb index ce3184b87..5b94c0337 100644 --- a/lib/git_stats/stats_view/charts/charts.rb +++ b/lib/git_stats/stats_view/charts/charts.rb @@ -3,7 +3,7 @@ module GitStats module StatsView module Charts class All - delegate :files_by_extension, :lines_by_extension, :files_by_date, :lines_by_date, to: :repo_charts + delegate :files_by_extension, :lines_by_extension, :files_by_date, :lines_by_date, :comments_by_date, to: :repo_charts delegate :commits_sum_by_author_by_date, :changed_lines_by_author_by_date, :insertions_by_author_by_date, :deletions_by_author_by_date, to: :authors_charts diff --git a/lib/git_stats/stats_view/charts/repo_charts.rb b/lib/git_stats/stats_view/charts/repo_charts.rb index a761cb159..3b6172259 100644 --- a/lib/git_stats/stats_view/charts/repo_charts.rb +++ b/lib/git_stats/stats_view/charts/repo_charts.rb @@ -47,6 +47,16 @@ module GitStats end end + def comments_by_date + Chart.new do |f| + f.date_chart( + data: @repo.comments_count_by_date, + title: :comments_by_date.t, + y_text: :comments.t + ) + end + end + end end end diff --git a/lib/git_stats/stats_view/view.rb b/lib/git_stats/stats_view/view.rb index 42e216ba2..d99dd0050 100644 --- a/lib/git_stats/stats_view/view.rb +++ b/lib/git_stats/stats_view/view.rb @@ -55,7 +55,8 @@ module GitStats activity: 'activity/by_date.html', authors: 'authors/best_authors.html', files: 'files/by_date.html', - lines: 'lines/by_date.html' + lines: 'lines/by_date.html', + comments: 'comments/by_date.html' } end diff --git a/spec/git_data/generator_spec.rb b/spec/git_data/generator_spec.rb index 7d1440c96..a04b97a4d 100644 --- a/spec/git_data/generator_spec.rb +++ b/spec/git_data/generator_spec.rb @@ -15,7 +15,7 @@ describe GitStats::Generator do it 'should pass command observer to repo' do repo = double('repo') - GitStats::GitData::Repo.should_receive(:new).with(path: repo_path, first_commit_sha: nil, last_commit_sha: "HEAD", tree_path: ".").and_return(repo) + GitStats::GitData::Repo.should_receive(:new).with(path: repo_path, first_commit_sha: nil, last_commit_sha: "HEAD", tree_path: ".", :comment_string=>"///").and_return(repo) generator = GitStats::Generator.new(repo_path, out_path) @@ -27,7 +27,7 @@ describe GitStats::Generator do it 'should render all templates with view data for this repo' do repo = double('repo') - GitStats::GitData::Repo.should_receive(:new).with(path: repo_path, first_commit_sha: nil, last_commit_sha: "HEAD", tree_path: ".").and_return(repo) + GitStats::GitData::Repo.should_receive(:new).with(path: repo_path, first_commit_sha: nil, last_commit_sha: "HEAD", tree_path: ".", :comment_string=>"///").and_return(repo) view_data = double('view_data') GitStats::StatsView::ViewData.should_receive(:new).with(repo).and_return(view_data) diff --git a/templates/comments/_comments.haml b/templates/comments/_comments.haml new file mode 100644 index 000000000..766507e71 --- /dev/null +++ b/templates/comments/_comments.haml @@ -0,0 +1,11 @@ +.tabbable.tabs-left + %ul.nav.nav-tabs + %li{class: page == :comments_by_date ? "active" : ""} + %a{:href => 'by_date.html'}= :comments_by_date.t + + .tab-content + .tab-pane.active + .page-header + %h1.pagination-centered= page.t + - if page == :comments_by_date + = high_stock("comments_by_date", charts.comments_by_date) diff --git a/templates/comments/by_date.haml b/templates/comments/by_date.haml new file mode 100644 index 000000000..7305abcb1 --- /dev/null +++ b/templates/comments/by_date.haml @@ -0,0 +1 @@ += render_partial('comments/_comments', page: :comments_by_date) \ No newline at end of file