git_stats/lib/git_stats/git_data/repo.rb

218 lines
6.0 KiB
Ruby
Raw Normal View History

2012-10-23 20:37:42 +02:00
# -*- encoding : utf-8 -*-
2012-10-13 17:20:06 +02:00
require 'git_stats/hash_initializable'
2012-10-09 22:34:02 +02:00
module GitStats
module GitData
class Repo
2012-10-13 17:20:06 +02:00
include HashInitializable
delegate :files, :files_by_extension, :files_by_extension_count, :lines_by_extension,
:files_count, :binary_files, :text_files, :lines_count, :comments_count, to: :last_commit
2012-10-09 22:34:02 +02:00
2012-10-13 17:20:06 +02:00
def initialize(params)
super(params)
@path = File.expand_path(@path)
@tree_path ||= "."
2012-10-09 22:34:02 +02:00
end
def path
@path ||= '.'
end
def first_commit_sha
@first_commit_sha
end
def last_commit_sha
@last_commit_sha ||= 'HEAD'
end
def tree_path
@tree_path ||= '.'
end
def comment_string
@comment_string ||= '//'
end
def tree
@tree ||= Tree.new(repo: self, relative_path: @tree_path)
end
2015-11-29 13:32:20 +01:00
def command_memoization
@command_memoization_map ||= {}
end
2012-10-12 18:20:07 +02:00
def authors
@authors ||= run_and_parse("git shortlog -se #{commit_range} #{tree_path}").map do |author|
2012-10-19 16:39:39 +02:00
Author.new(repo: self, name: author[:name], email: author[:email])
end
2012-10-09 22:34:02 +02:00
end
2012-10-12 18:20:07 +02:00
def commits
@commits ||= run_and_parse("git rev-list --pretty=format:'%h|%at|%ai|%aE' #{commit_range} #{tree_path} | grep -v commit").map do |commit_line|
2012-10-19 21:17:16 +02:00
Commit.new(
repo: self,
2012-10-20 22:38:11 +02:00
sha: commit_line[:sha],
2012-10-19 21:17:16 +02:00
stamp: commit_line[:stamp],
date: DateTime.parse(commit_line[:date]),
author: authors.first! { |a| a.email == commit_line[:author_email] }
2012-10-19 21:17:16 +02:00
)
end.sort_by! { |e| e.date }
end
2012-10-19 22:01:01 +02:00
def commits_period
commits.map(&:date).minmax
end
2012-10-21 18:25:11 +02:00
def commits_count_by_author(limit = 4)
Hash[authors.map { |author| [author, author.commits.size] }.sort_by { |author, commits| -commits }[0..limit]]
2012-10-21 17:34:05 +02:00
end
2012-10-21 23:53:31 +02:00
[:insertions, :deletions, :changed_lines].each do |method|
2012-10-21 22:41:54 +02:00
define_method "#{method}_by_author" do |limit = 4|
Hash[authors.map { |author| [author, author.send(method)] }.sort_by { |author, lines| -lines }[0..limit]]
end
2012-10-20 21:28:25 +02:00
end
2012-10-21 13:19:37 +02:00
def files_count_by_date
@files_count_each_day ||= Hash[commits.map { |commit|
[commit.date.to_date, commit.files_count]
}]
2012-10-20 00:30:00 +02:00
end
2012-10-21 13:19:37 +02:00
def lines_count_by_date
sum = 0
@lines_count_each_day ||= Hash[commits.map { |commit|
sum += commit.short_stat.insertions
sum -= commit.short_stat.deletions
[commit.date.to_date, sum]
}]
2012-10-20 00:30:00 +02:00
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
2015-11-29 13:32:20 +01:00
def files_by_extension_by_date
file_counts_by_date_by_extension = {}
extensions_sums = {}
commits.map do |commit|
commit.files_by_extension_count.map do |ext, count|
extensions_sums[ext] ||= 0;
extensions_sums[ext] = count;
file_counts_by_date_by_extension[ext] ||= {};
file_counts_by_date_by_extension[ext][commit.date.to_date] = extensions_sums[ext]
end
end
@multi_data_file_counts_by_date ||= file_counts_by_date_by_extension.map { |ext, data|
{
name: ext || "NO EXTENSION",
data: data.fill_empty_days!(aggregated:true)
}
}
end
def lines_by_extension_by_date
lines_by_date_by_extension = {}
extensions_sums = {}
commits.map do |commit|
commit.lines_by_extension.map do |ext, count|
extensions_sums[ext] ||= 0;
extensions_sums[ext] = count;
lines_by_date_by_extension[ext] ||= {};
lines_by_date_by_extension[ext][commit.date.to_date] = extensions_sums[ext]
end
end
@multi_data_lines_by_date ||= lines_by_date_by_extension.map { |ext, data|
{
name: ext || "NO EXTENSION",
data: data.fill_empty_days!(aggregated:true)
}
}
end
2012-10-19 17:35:33 +02:00
def last_commit
commits.last
end
2012-10-19 15:51:24 +02:00
def commit_range
@first_commit_sha.blank? ? last_commit_sha : "#@first_commit_sha..#{last_commit_sha}"
2012-10-19 15:51:24 +02:00
end
def short_stats
@short_stats ||= commits.map(&:short_stat)
2012-10-09 22:34:02 +02:00
end
def comment_stats
@comment_stats ||= commits.map(&:comment_stat)
end
2012-10-09 22:34:02 +02:00
def activity
2012-10-12 18:24:28 +02:00
@activity ||= Activity.new(commits)
2012-10-09 22:34:02 +02:00
end
def project_version
@project_version ||= run("git rev-parse --short #{commit_range}").strip
2012-10-09 22:34:02 +02:00
end
def project_name
@project_name ||= (File.expand_path(File.join(path, tree_path)).sub(File.dirname(File.expand_path(path))+File::SEPARATOR,"") || File.basename(path))
2012-10-09 22:34:02 +02:00
end
2012-10-12 18:20:07 +02:00
2012-10-19 16:57:49 +02:00
def run(command)
2015-11-29 13:32:20 +01:00
if (command_memoization[command])
command_memoization[command]
else
result = command_runner.run(path, command)
invoke_command_observers(command, result)
command_memoization[command] = result
result
end
2012-10-19 16:57:49 +02:00
end
def run_and_parse(command)
result = run(command)
command_parser.parse(command, result)
end
2012-10-19 21:11:47 +02:00
def command_runner
@command_runner ||= CommandRunner.new
end
2012-10-19 16:57:49 +02:00
def command_parser
@command_parser ||= CommandParser.new
end
2012-10-19 21:11:47 +02:00
def add_command_observer(proc=nil, &block)
command_observers << block if block_given?
command_observers << proc if proc
2012-10-19 16:57:49 +02:00
end
2012-10-13 12:38:07 +02:00
def to_s
"#{self.class} #@path"
end
2012-10-13 13:27:15 +02:00
def ==(other)
self.path == other.path
end
2012-10-19 21:11:47 +02:00
private
def command_observers
@command_observers ||= []
end
def invoke_command_observers(command, result)
command_observers.each { |o| o.call(command, result) }
end
2012-10-09 22:34:02 +02:00
end
end
2012-10-23 20:37:42 +02:00
end