git_fame 2.5.2 → 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/exe/git-fame +9 -0
- data/lib/git_fame/author.rb +5 -75
- data/lib/git_fame/base.rb +10 -523
- data/lib/git_fame/collector.rb +45 -0
- data/lib/git_fame/command.rb +171 -0
- data/lib/git_fame/contribution.rb +12 -0
- data/lib/git_fame/diff.rb +25 -0
- data/lib/git_fame/error.rb +5 -0
- data/lib/git_fame/extension.rb +16 -0
- data/lib/git_fame/filter.rb +43 -0
- data/lib/git_fame/render/extension.rb +26 -0
- data/lib/git_fame/render.rb +38 -0
- data/lib/git_fame/result.rb +29 -4
- data/lib/git_fame/types.rb +11 -0
- data/lib/git_fame/version.rb +3 -1
- data/lib/git_fame.rb +16 -3
- metadata +82 -111
- data/.gitignore +0 -20
- data/.gitmodules +0 -3
- data/.rspec +0 -7
- data/.travis.yml +0 -16
- data/Gemfile +0 -4
- data/LICENSE +0 -22
- data/README.md +0 -140
- data/Rakefile +0 -15
- data/bin/git-fame +0 -58
- data/git_fame.gemspec +0 -42
- data/lib/git_fame/blame_parser.rb +0 -83
- data/lib/git_fame/commit_range.rb +0 -27
- data/lib/git_fame/errors.rb +0 -6
- data/lib/git_fame/file.rb +0 -13
- data/lib/git_fame/helper.rb +0 -11
- data/lib/git_fame/silent_progressbar.rb +0 -20
- data/spec/bin_spec.rb +0 -116
- data/spec/git_fame_spec.rb +0 -488
- data/spec/spec_helper.rb +0 -65
- data/spec/support/startup.rb +0 -21
data/git_fame.gemspec
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
require File.expand_path('../lib/git_fame/version', __FILE__)
|
3
|
-
|
4
|
-
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = ["Linus Oleander"]
|
6
|
-
gem.email = ["linus@oleander.nu"]
|
7
|
-
gem.description = "A command-line tool that helps you summarize and pretty-print collaborators in a git repository based on contributions"
|
8
|
-
gem.summary = %q{
|
9
|
-
git-fame is a command-line tool that helps you summarize and pretty-print collaborators in a git repository based on contributions. A Ruby wrapper for git-blame if you will.
|
10
|
-
|
11
|
-
Generates stats like:
|
12
|
-
- Number of files changed by a user
|
13
|
-
- Number of commits by user
|
14
|
-
- Lines of code by a user}
|
15
|
-
|
16
|
-
gem.homepage = "http://oleander.io/git-fame-rb"
|
17
|
-
|
18
|
-
gem.files = `git ls-files`.split($\)
|
19
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
20
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
21
|
-
gem.name = "git_fame"
|
22
|
-
gem.require_paths = ["lib"]
|
23
|
-
gem.version = GitFame::VERSION
|
24
|
-
|
25
|
-
gem.add_dependency("progressbar", "~> 0.21.0")
|
26
|
-
gem.add_dependency("trollop", "~> 2.1.2")
|
27
|
-
gem.add_dependency("hirb", "~> 0.7.3")
|
28
|
-
gem.add_dependency("scrub_rb", "~> 1.0.1")
|
29
|
-
gem.add_dependency("memoist", "~> 0.14.0")
|
30
|
-
gem.add_dependency("method_profiler", "~> 2.0.1")
|
31
|
-
|
32
|
-
gem.add_development_dependency("rspec", "~> 3.4.0")
|
33
|
-
gem.add_development_dependency("rspec-collection_matchers", "~> 1.1.2")
|
34
|
-
gem.add_development_dependency("rake", "~> 10.4.2")
|
35
|
-
gem.add_development_dependency("coveralls", "~> 0.8.1")
|
36
|
-
gem.add_development_dependency("json", "~> 1.8.3")
|
37
|
-
gem.add_development_dependency("tins", "~> 1.6.0")
|
38
|
-
gem.add_development_dependency("term-ansicolor", "~> 1.3.2")
|
39
|
-
gem.add_development_dependency("colorize")
|
40
|
-
|
41
|
-
gem.required_ruby_version = ">= 1.9.2"
|
42
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
# Extracted from the dolt gem. Currently not maintained.
|
2
|
-
# Source: https://docs.omniref.com/ruby/gems/libdolt/0.33.14/symbols/Dolt::Git::Blame::PorcelainParser
|
3
|
-
module GitFame
|
4
|
-
class BlameParser
|
5
|
-
def initialize(output)
|
6
|
-
@output = output
|
7
|
-
@commits = {}
|
8
|
-
end
|
9
|
-
def parse
|
10
|
-
lines = @output.split("\n")
|
11
|
-
chunks = []
|
12
|
-
while lines.length > 0
|
13
|
-
chunk = extract_header(lines)
|
14
|
-
affected_lines = extract_lines(lines, chunk[:num_lines])
|
15
|
-
if chunks.last && chunk[:oid] == chunks.last[:oid]
|
16
|
-
chunks.last[:lines].concat(affected_lines)
|
17
|
-
else
|
18
|
-
chunk[:lines] = affected_lines
|
19
|
-
chunks << chunk
|
20
|
-
end
|
21
|
-
end
|
22
|
-
chunks
|
23
|
-
rescue Exception => error
|
24
|
-
raise Error, "Failed parsing Procelain: #{error.message}"
|
25
|
-
end
|
26
|
-
|
27
|
-
def is_header?(line)
|
28
|
-
line =~ /^[0-9a-f]{40} \d+ \d+ \d+$/
|
29
|
-
end
|
30
|
-
|
31
|
-
def extract_header(lines)
|
32
|
-
header = lines.shift
|
33
|
-
pieces = header.scan(/^([0-9a-f]{40}) (\d+) (\d+) (\d+)$/).first
|
34
|
-
header = { :oid => pieces.first, :num_lines => pieces[3].to_i }
|
35
|
-
if lines.first =~ /^author/
|
36
|
-
header[:author] = extract_hash(lines, :author)
|
37
|
-
header[:committer] = extract_hash(lines, :committer)
|
38
|
-
header[:summary] = extract(lines, "summary")
|
39
|
-
header[:boundary] = extract(lines, "boundary")
|
40
|
-
throwaway = lines.shift until throwaway =~ /^filename/
|
41
|
-
@commits[header[:oid]] = header
|
42
|
-
else
|
43
|
-
header[:author] = @commits[header[:oid]][:author]
|
44
|
-
header[:committer] = @commits[header[:oid]][:committer]
|
45
|
-
header[:summary] = @commits[header[:oid]][:summary]
|
46
|
-
end
|
47
|
-
header
|
48
|
-
end
|
49
|
-
|
50
|
-
def extract_lines(lines, num)
|
51
|
-
extracted = []
|
52
|
-
num.times do
|
53
|
-
if extracted.length > 0
|
54
|
-
line = lines.shift # Header for next line
|
55
|
-
end
|
56
|
-
content = lines.shift # Actual content
|
57
|
-
next unless content
|
58
|
-
extracted.push(content[1..content.length]) # 8 spaces padding
|
59
|
-
end
|
60
|
-
extracted
|
61
|
-
end
|
62
|
-
|
63
|
-
def extract_hash(lines, type)
|
64
|
-
{
|
65
|
-
:name => extract(lines, "#{type}"),
|
66
|
-
:mail => extract(lines, "#{type}-mail").gsub(/[<>]/, ""),
|
67
|
-
:time => (Time.at(extract(lines, "#{type}-time").to_i).utc +
|
68
|
-
Time.zone_offset(extract(lines, "#{type}-tz")))
|
69
|
-
}
|
70
|
-
end
|
71
|
-
def extract(lines, thing)
|
72
|
-
if thing == "boundary"
|
73
|
-
if (line = lines.shift) == thing
|
74
|
-
return true
|
75
|
-
else
|
76
|
-
return ! lines.unshift(line)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
lines.shift.split("#{thing} ")[1]
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
class CommitRange < Struct.new(:data, :current_branch)
|
2
|
-
SHORT_LENGTH = 7
|
3
|
-
|
4
|
-
def to_s(short = false)
|
5
|
-
@_to_s ||= range.map do |commit|
|
6
|
-
short ? shorten(commit) : commit
|
7
|
-
end.join("..")
|
8
|
-
end
|
9
|
-
|
10
|
-
def is_range?
|
11
|
-
data.is_a?(Array)
|
12
|
-
end
|
13
|
-
|
14
|
-
def range
|
15
|
-
is_range? ? data : [data]
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def branch?(commit)
|
21
|
-
current_branch == commit
|
22
|
-
end
|
23
|
-
|
24
|
-
def shorten(commit)
|
25
|
-
branch?(commit) ? commit : commit[0..SHORT_LENGTH]
|
26
|
-
end
|
27
|
-
end
|
data/lib/git_fame/errors.rb
DELETED
data/lib/git_fame/file.rb
DELETED
data/lib/git_fame/helper.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
module GitFame
|
2
|
-
module Helper
|
3
|
-
#
|
4
|
-
# @value Fixnum Value to be formated
|
5
|
-
# @return String Formated according ActionView::Helpers::NumberHelper.number_with_delimiter
|
6
|
-
#
|
7
|
-
def number_with_delimiter(value)
|
8
|
-
value.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require "progressbar"
|
2
|
-
|
3
|
-
class SilentProgressbar
|
4
|
-
#
|
5
|
-
# @name String Name for progressbar
|
6
|
-
# @steps Fixnum Total number of steps
|
7
|
-
# @active Should progressbar be visible?
|
8
|
-
#
|
9
|
-
def initialize(name, steps, active = false)
|
10
|
-
@bp = ProgressBar.new(name, steps) if active
|
11
|
-
end
|
12
|
-
|
13
|
-
def finish
|
14
|
-
@bp && @bp.finish
|
15
|
-
end
|
16
|
-
|
17
|
-
def increment
|
18
|
-
@bp && @bp.inc
|
19
|
-
end
|
20
|
-
end
|
data/spec/bin_spec.rb
DELETED
@@ -1,116 +0,0 @@
|
|
1
|
-
describe "bin/git-fame" do
|
2
|
-
it "should include the authors name" do
|
3
|
-
run("--help").should include_output("Linus Oleander")
|
4
|
-
end
|
5
|
-
|
6
|
-
it "should include the the current version" do
|
7
|
-
run("--version").should include_output(GitFame::VERSION)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should fail on invalid option" do
|
11
|
-
run("--nope").should_not be_a_succees
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should not accept a non-existent repository" do
|
15
|
-
run("--repository=??").should_not be_a_succees
|
16
|
-
end
|
17
|
-
|
18
|
-
[
|
19
|
-
"--sort=name",
|
20
|
-
"--sort=commits",
|
21
|
-
"--sort=loc",
|
22
|
-
"--hide-progressbar",
|
23
|
-
"--whitespace",
|
24
|
-
"--by-type",
|
25
|
-
"--include=hello",
|
26
|
-
"--exclude=hello",
|
27
|
-
"--extension=rb,ln",
|
28
|
-
"--branch=master",
|
29
|
-
"--format=csv",
|
30
|
-
"--format=pretty",
|
31
|
-
"--before=2010-01-01",
|
32
|
-
"--after=1980-01-01",
|
33
|
-
"--version",
|
34
|
-
"--help",
|
35
|
-
"--verbose",
|
36
|
-
"--everything",
|
37
|
-
"--timeout=10",
|
38
|
-
"--timeout=-1"
|
39
|
-
].each do |option|
|
40
|
-
it "should support #{option}" do
|
41
|
-
run(option).should be_a_succees
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should sort by loc by default" do
|
46
|
-
run("--sort=loc", "--progressbar=0").first.should eq(run("--progressbar=0").first)
|
47
|
-
end
|
48
|
-
|
49
|
-
context "dates" do
|
50
|
-
it "should fail on invalid before date" do
|
51
|
-
res = run("--before='---'")
|
52
|
-
res.should_not be_a_succees
|
53
|
-
res.should include_output("'---' is not a valid date")
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should fail on invalid after date" do
|
57
|
-
res = run("--after='---'")
|
58
|
-
res.should_not be_a_succees
|
59
|
-
res.should include_output("'---' is not a valid date")
|
60
|
-
end
|
61
|
-
|
62
|
-
it "should not print stack trace on invalid dates (--after)" do
|
63
|
-
res = run("--after='---'")
|
64
|
-
res.should_not be_a_succees
|
65
|
-
res.should_not include_output("GitFame::Error")
|
66
|
-
end
|
67
|
-
|
68
|
-
it "should fail on invalid timeout" do
|
69
|
-
run("--timeout=hello").should_not be_a_succees
|
70
|
-
run("--timeout=").should_not be_a_succees
|
71
|
-
run("--timeout=0").should_not be_a_succees
|
72
|
-
run("--timeout=-2").should_not be_a_succees
|
73
|
-
end
|
74
|
-
|
75
|
-
it "should not print stack trace on invalid dates (--before)" do
|
76
|
-
res = run("--before='---'")
|
77
|
-
res.should_not be_a_succees
|
78
|
-
res.should_not include_output("GitFame::Error")
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should not print stack trace on out of span (--before)" do
|
82
|
-
res = run("--before='1910-01-01'")
|
83
|
-
res.should_not be_a_succees
|
84
|
-
res.should_not include_output("GitFame::Error")
|
85
|
-
end
|
86
|
-
|
87
|
-
it "should not print stack trace on out of span (--after)" do
|
88
|
-
res = run("--after='2100-01-01'")
|
89
|
-
res.should_not be_a_succees
|
90
|
-
res.should_not include_output("GitFame::Error")
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context "sort" do
|
95
|
-
it "should fail on non existing option" do
|
96
|
-
run("--sort=-----").should_not be_a_succees
|
97
|
-
end
|
98
|
-
|
99
|
-
results = []
|
100
|
-
GitFame::SORT.each do |option|
|
101
|
-
it "should be able to sort by #{option}" do
|
102
|
-
out = run("--sort=#{option}")
|
103
|
-
out.should be_a_succees
|
104
|
-
# TODO: Not a impl. problem
|
105
|
-
# Just not enough data
|
106
|
-
unless option == "name"
|
107
|
-
results.push(out.first)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
it "#{GitFame::SORT.join(", ")} should not output the same thing" do
|
113
|
-
results.uniq.sort.should eq(results.sort)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|