Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f8b05f4

Browse files
Merge pull request #61 from kevinjalbert/move-to-rugged
Move from Grit to Rugged for git processing
2 parents ed24dae + eb92d38 commit f8b05f4

23 files changed

+240
-423
lines changed

‎.ruby-version‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.9.3-p392
1+
2.0.0

‎.travis.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
language: ruby
22

33
rvm:
4-
- 1.9.2
54
- 1.9.3
5+
- 2.0.0
66

77
bundler_args: --without darwin debug
88

‎Rakefile‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ end
1616

1717
desc "Run git_statistics on current/specified directory (for debugging)"
1818
task :run, :dir do |t, args|
19-
puts args[:dir]
2019
Bundler.require(:debug)
2120
require 'git_statistics'
2221
GitStatistics::CLI.new(args[:dir]).execute

‎git_statistics.gemspec‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ Gem::Specification.new do |gem|
1414
gem.files = Dir['lib/**/*']
1515
gem.test_files = Dir['spec/**/*_spec.rb']
1616
gem.executables = %w[ git_statistics git-statistics ]
17-
gem.required_ruby_version = '>= 1.9.1'
17+
gem.required_ruby_version = '>= 1.9.3'
1818

1919
gem.add_dependency('json')
20-
gem.add_dependency('grit')
20+
gem.add_dependency('rugged')
2121
gem.add_dependency('language_sniffer')
2222

2323
gem.add_development_dependency "rspec", "~> 2.12.0"

‎lib/git_statistics.rb‎

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ module GitStatistics
44
class CLI
55
attr_reader :repository, :options
66

7+
DEFAULT_BRANCH = "master"
8+
79
def initialize(dir)
8-
@repository = dir.nil? ? Repo.new(Dir.pwd) : Repo.new(dir)
10+
repository_location = dir.nil? ? Rugged::Repository.discover(Dir.pwd) : Rugged::Repository.discover(dir)
11+
@repository = Rugged::Repository.new(repository_location)
912
@collected = false
1013
@collector = nil
1114
@options = OpenStruct.new(
@@ -15,7 +18,7 @@ def initialize(dir)
1518
update: false,
1619
sort: "commits",
1720
top: 0,
18-
branch: false,
21+
branch: DEFAULT_BRANCH,
1922
verbose: false,
2023
debug: false,
2124
limit: 100
@@ -35,14 +38,13 @@ def collect_and_only_update
3538
if options.update
3639
# Ensure commit directory is present
3740
@collector = Collector.new(repository, options.limit, false, options.pretty)
38-
commits_directory = repository.working_dir + ".git_statistics"
41+
commits_directory = repository.workdir + ".git_statistics/"
3942
FileUtils.mkdir_p(commits_directory)
4043
file_count = Utilities.number_of_matching_files(commits_directory, /\d+\.json/) - 1
4144

4245
if file_count >= 0
43-
time_since = Utilities.get_modified_time(commits_directory + "#{file_count}.json")
44-
# Only use --since if there is data present
45-
@collector.collect(options.branch, {:since => time_since})
46+
time_since = Utilities.get_modified_time(commits_directory + "#{file_count}.json").to_s
47+
@collector.collect({:branch => options.branch, :time_since => time_since})
4648
@collected = true
4749
end
4850
end
@@ -59,7 +61,7 @@ def output_results
5961

6062
def fresh_collect!
6163
@collector = Collector.new(repository, options.limit, true, options.pretty)
62-
@collector.collect(options.branch)
64+
@collector.collect({:branch=>options.branch})
6365
end
6466

6567
def parse_options
@@ -83,8 +85,8 @@ def parse_options
8385
opt.on "-t", "--top N", Float,"Show the top N authors in results" do |value|
8486
options.top = value
8587
end
86-
opt.on "-b", "--branch", "Use current branch for statistics (otherwise all branches)" do
87-
options.branch = true
88+
opt.on "-b", "--branch BRANCH", "Use the specified branch for statistics (otherwise the master branch is used)" do |branch|
89+
options.branch = branch
8890
end
8991
opt.on "-v", "--verbose", "Verbose output (shows INFO level log statements)" do
9092
options.verbose = true

‎lib/git_statistics/blob_finder.rb‎

Lines changed: 0 additions & 54 deletions
This file was deleted.

‎lib/git_statistics/collector.rb‎

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,67 @@ class Collector
44
attr_accessor :repo, :commits_path, :commits
55

66
def initialize(repo, limit, fresh, pretty)
7-
Grit::Git.git_timeout = 0
8-
Grit::Git.git_max_size = 0
9-
107
@repo = repo
11-
@commits_path = repo.working_dir + ".git_statistics"
8+
@commits_path = repo.workdir + ".git_statistics"
129
@commits = Commits.new(@commits_path, fresh, limit, pretty)
1310
end
1411

15-
def collect(branch, options = {})
16-
# Collect branches to use for git log
17-
branches = branch ? [] : @repo.branches.compact.map(&:name)
18-
Grit::Commit.find_all(@repo, nil, options).each do |commit|
19-
extract_commit(commit)
20-
@commits.flush_commits
12+
def collect(options = {})
13+
branch = options[:branch] ? options[:branch] : CLI::DEFAULT_BRANCH
14+
branch_head = Rugged::Branch.lookup(repo, branch).tip
15+
16+
walker = Rugged::Walker.new(repo)
17+
walker.push(branch_head)
18+
19+
walker.each_with_index do |commit, count|
20+
if valid_commit?(commit, options)
21+
extract_commit(commit, count + 1)
22+
@commits.flush_commits
23+
end
2124
end
25+
2226
@commits.flush_commits(true)
2327
end
2428

29+
def valid_commit?(commit, options)
30+
if !options[:time_since].nil?
31+
return false unless commit.author[:time] > DateTime.parse(options[:time_since].to_s).to_time
32+
end
33+
34+
if !options[:time_until].nil?
35+
return false unless commit.author[:time] < DateTime.parse(options[:time_until].to_s).to_time
36+
end
37+
38+
return true
39+
end
40+
2541
def acquire_commit_meta(commit_summary)
2642
# Initialize commit data
27-
data = (@commits[commit_summary.sha] ||= Hash.new(0))
43+
data = (@commits[commit_summary.oid] ||= Hash.new(0))
2844

29-
data[:author] = commit_summary.author.name
30-
data[:author_email] = commit_summary.author.email
31-
data[:time] = commit_summary.authored_date.to_s
45+
data[:author] = commit_summary.author[:name]
46+
data[:author_email] = commit_summary.author[:email]
47+
data[:time] = commit_summary.author[:time].to_s
3248
data[:merge] = commit_summary.merge?
3349
data[:additions] = commit_summary.additions
3450
data[:deletions] = commit_summary.deletions
3551
data[:net] = commit_summary.net
36-
data[:new_files] = commit_summary.new_files
37-
data[:removed_files] = commit_summary.removed_files
38-
data[:files] = commit_summary.files
52+
data[:added_files] = commit_summary.added_files
53+
data[:deleted_files] = commit_summary.deleted_files
54+
data[:modified_files] = commit_summary.modified_files
55+
data[:files] = commit_summary.file_stats.map{ |file| file.to_json }
3956

4057
return data
4158
end
4259

43-
def extract_commit(commit)
44-
unless commit.nil?
45-
commit_summary = CommitSummary.new(commit)
46-
Log.info "Extracting #{commit_summary.sha}"
60+
def extract_commit(commit, count)
61+
Log.info "Extracting(#{count}) #{commit.oid}"
62+
commit_summary = CommitSummary.new(@repo, commit)
4763

48-
# Acquire meta information about commit
49-
commit_data = acquire_commit_meta(commit_summary)
64+
# Acquire meta information about commit
65+
commit_data = acquire_commit_meta(commit_summary)
5066

51-
return commit_data
52-
end
67+
return commit_data
5368
end
5469

5570
end

‎lib/git_statistics/commit_summary.rb‎

Lines changed: 19 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
module GitStatistics
22
class CommitSummary < SimpleDelegator
3-
def initialize(commit)
3+
def initialize(repo,commit)
44
super(commit)
5+
@repo = repo
6+
@diff = diff(commit.parents.first)
7+
@patches = @diff.patches
58
end
69

710
# A Git commit is a merge if it has more than one parent
@@ -10,13 +13,18 @@ def merge?
1013
end
1114

1215
# How many files were removed in this commit
13-
def removed_files
14-
cached_show.select { |diff| diff.deleted_file == true }.count
16+
def deleted_files
17+
file_stats.select { |file| file.status == :deleted }.count
1518
end
1619

1720
# How many files were added in this commit
18-
def new_files
19-
cached_show.select { |diff| diff.new_file == true }.count
21+
def added_files
22+
file_stats.select { |file| file.status == :added }.count
23+
end
24+
25+
# How many files were modified (not added/deleted) in this commit
26+
def modified_files
27+
file_stats.select { |file| file.status == :modified }.count
2028
end
2129

2230
# How many total additions in this commit?
@@ -35,18 +43,18 @@ def net
3543
end
3644

3745
def file_stats
38-
@cached_file_stats ||= diffstats.map { |diff| DiffSummary.new(diff,current_tree) }
46+
@cached_file_stats ||= diffstats.map { |diff| DiffSummary.new(@repo,diff) }
3947
end
4048

41-
LanguageSummary = Struct.new(:name, :additions, :deletions, :net)
49+
LanguageSummary = Struct.new(:name, :additions, :deletions, :net,:added_files,:deleted_files,:modified_files)
4250

4351
# Array of LanguageSummary objects (one for each language) for simple calculations
4452
def languages
4553
grouped_language_files.collect do |language, stats|
4654
additions = summarize(stats, :additions)
4755
deletions = summarize(stats, :deletions)
4856
net = summarize(stats, :net)
49-
LanguageSummary.new(language, additions, deletions, net)
57+
LanguageSummary.new(language, additions, deletions, net,added_files,deleted_files,modified_files)
5058
end
5159
end
5260

@@ -55,72 +63,13 @@ def grouped_language_files
5563
file_stats.group_by(&:language)
5664
end
5765

58-
FileSummary = Struct.new(:name, :language, :additions, :deletions, :net, :filestatus)
59-
60-
# Array of FileSummary objects (one for each file) for simple calculations
61-
def files
62-
file_stats.collect{ |stats| determine_file_summary(stats) }
63-
end
64-
65-
def cached_show
66-
@cached_commit_show ||= show
67-
end
68-
6966
# Files touched in this commit
70-
def file_names
71-
diffstats.map(&:filename)
72-
end
73-
74-
# Fetch the current Grit::Repo tree from this commit
75-
def current_tree
76-
@current_tree ||= repo.tree(sha)
67+
def filenames
68+
file_stats.map(&:filename)
7769
end
7870

7971
private
8072

81-
def determine_file_summary(stats)
82-
filestatus = :modified
83-
language = stats.language
84-
85-
# Determine if this file could be a new or deleted file
86-
if (stats.additions > 0 && stats.deletions == 0) || (stats.additions == 0 && stats.deletions > 0)
87-
# Extract file status from commit's diff object
88-
cached_show.each do |diff|
89-
if stats.filename == diff.b_path
90-
filestatus = :create if diff.new_file
91-
filestatus = :delete if diff.deleted_file
92-
break
93-
end
94-
end
95-
end
96-
97-
# Determine language of blob
98-
if stats.tree?
99-
# Trees have no language (the tree's blobs are still processed via the remainder diffstats)
100-
language = "Unknown"
101-
elsif stats.submodule?
102-
language = "Submodule"
103-
elsif stats.blob.nil?
104-
# If blob is nil (i.e., deleted file) grab the previous version of this blob using the parents of the current commit
105-
blob = BlobFinder.get_blob(self.parents.first, stats.filename)
106-
blob = BlobFinder.get_blob(self.parents.last, stats.filename) if blob.nil?
107-
108-
# Determine language of newly found blob
109-
if blob.kind_of? Grit::Tree
110-
language = "Unknown"
111-
elsif blob.kind_of? Grit::Submodule
112-
language = "Submodule"
113-
elsif blob.nil? || blob.language.nil?
114-
language = "Unknown"
115-
else
116-
language = blob.language.to_s
117-
end
118-
end
119-
120-
# TODO Converts file summary into hash to keep json compatibility (for now)
121-
Hash[FileSummary.new(stats.filename, language, stats.additions, stats.deletions, stats.net, filestatus).each_pair.to_a]
122-
end
123-
12473
def summarize(stats, what)
12574
stats.map(&what).inject(0, :+)
12675
end
@@ -130,19 +79,7 @@ def commit_summary(what)
13079
end
13180

13281
def diffstats
133-
if merge?
134-
merge_diffstats
135-
else
136-
stats.to_diffstat
137-
end
138-
end
139-
140-
# Hackery coming...
141-
DIFFSTAT_REGEX = /([-|\d]+)\s+([-|\d]+)\s+(.+)/i
142-
def merge_diffstats
143-
native_diff = repo.git.native(:diff, {numstat: true}, parents.join("..."))
144-
per_file_info = native_diff.scan(DIFFSTAT_REGEX)
145-
per_file_info.map { |add, del, file| Grit::DiffStat.new(file, add.to_i, del.to_i) }
82+
@patches
14683
end
14784

14885
end

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /