caelum-git-reports 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +10 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/bin/git-report.rb +48 -0
- data/lib/html_report.rb +34 -0
- data/lib/html_summary.rb +63 -0
- data/lib/reporter.rb +58 -0
- data/lib/repository.rb +72 -0
- data/lib/template.rb +46 -0
- data/spec/html_report_spec.rb +53 -0
- data/spec/html_summary_spec.rb +58 -0
- data/spec/reporter_spec.rb +5 -0
- data/spec/repository_spec.rb +52 -0
- data/spec/spec_helper.rb +8 -0
- metadata +75 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Caue Guerra
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "git-reports"
|
8
|
+
gem.summary = "Git report tool"
|
9
|
+
gem.email = "caue.guerra@gmail.com"
|
10
|
+
gem.homepage = "http://github.com/caelum/git-reports"
|
11
|
+
gem.authors = ["Caue Guerra", "Pedro Matiello"]
|
12
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
13
|
+
end
|
14
|
+
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'spec/rake/spectask'
|
20
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
21
|
+
spec.libs << 'lib' << 'spec'
|
22
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
23
|
+
spec.spec_opts = ["--colour --format specdoc"]
|
24
|
+
end
|
25
|
+
|
26
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
27
|
+
spec.libs << 'lib' << 'spec'
|
28
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
29
|
+
spec.rcov = true
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
task :default => :spec
|
34
|
+
|
35
|
+
require 'rake/rdoctask'
|
36
|
+
Rake::RDocTask.new do |rdoc|
|
37
|
+
if File.exist?('VERSION.yml')
|
38
|
+
config = YAML.load(File.read('VERSION.yml'))
|
39
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
40
|
+
else
|
41
|
+
version = ""
|
42
|
+
end
|
43
|
+
|
44
|
+
rdoc.rdoc_dir = 'rdoc'
|
45
|
+
rdoc.title = "caelum-git-reports #{version}"
|
46
|
+
rdoc.rdoc_files.include('README*')
|
47
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
+
end
|
49
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/bin/git-report.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Load path
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
|
7
|
+
# Requires
|
8
|
+
require 'reporter'
|
9
|
+
require 'date'
|
10
|
+
require 'html_report'
|
11
|
+
require 'html_summary'
|
12
|
+
|
13
|
+
# Command line arguments
|
14
|
+
workdir = ARGV[0]
|
15
|
+
days = ARGV[1].to_i
|
16
|
+
max_commits = ARGV[2].to_i
|
17
|
+
if (max_commits <= 0)
|
18
|
+
max_commits = 50
|
19
|
+
end
|
20
|
+
|
21
|
+
# Action!
|
22
|
+
if (workdir and days > 0)
|
23
|
+
puts "Git stats for repositories under #{workdir}"
|
24
|
+
|
25
|
+
reporter = Reporter.new(workdir)
|
26
|
+
reporter.extract_all_stats(Date.new - days) do |name|
|
27
|
+
puts "Checking #{name}..."
|
28
|
+
end
|
29
|
+
|
30
|
+
now = Time.now.strftime("%Y.%m.%d")
|
31
|
+
|
32
|
+
# Repository stats
|
33
|
+
repository_html = File.new("repositories-#{now}-#{days}.html", "w")
|
34
|
+
repository_html.puts HtmlReport.new(reporter.repository_stats, "Statistics for repositories", days).generate
|
35
|
+
repository_html.close
|
36
|
+
|
37
|
+
# Commiter stats
|
38
|
+
commiter_html = File.new("commiters-#{now}-#{days}.html", "w")
|
39
|
+
commiter_html.puts HtmlReport.new(reporter.commiter_stats, "Statistics for commiters", days).generate
|
40
|
+
commiter_html.close
|
41
|
+
|
42
|
+
# Commit summary
|
43
|
+
summary_html = File.new("summary-#{now}-#{days}.html", "w")
|
44
|
+
summary_html.puts HtmlSummary.new(reporter.repository_summaries, "Summary", days, max_commits).generate
|
45
|
+
summary_html.close
|
46
|
+
else
|
47
|
+
puts "Usage: git-report.rb <path to repositories> <number of days to look back> [<number of commits in summary>]"
|
48
|
+
end
|
data/lib/html_report.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'template'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
class HtmlReport
|
5
|
+
|
6
|
+
include Template
|
7
|
+
|
8
|
+
def initialize(stats, title, days)
|
9
|
+
@stats = stats
|
10
|
+
@title = title
|
11
|
+
@days = days
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate
|
15
|
+
report = ''
|
16
|
+
|
17
|
+
from = (Time.now - @days*60*60*24).strftime("%Y.%m.%d")
|
18
|
+
to = Time.now.strftime("%Y.%m.%d")
|
19
|
+
|
20
|
+
report << Template::HEAD.gsub('%TITLE%', @title).gsub("%FROM%", from).gsub('%TO%', to)
|
21
|
+
for major in @stats.keys
|
22
|
+
report << Template::MAJOR_HEAD.gsub('%MAJOR%', major)
|
23
|
+
sum = 0
|
24
|
+
for minor, lines in @stats[major]
|
25
|
+
report << Template::MINOR.gsub('%MINOR%', minor).gsub('%LINES%', lines.to_s)
|
26
|
+
sum += lines
|
27
|
+
end
|
28
|
+
report << Template::MINOR.gsub('%MINOR%', '.').gsub('%LINES%', sum.to_s)
|
29
|
+
report << Template::MAJOR_TAIL
|
30
|
+
end
|
31
|
+
report << Template::TAIL
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/html_summary.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'template'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
class HtmlSummary
|
5
|
+
|
6
|
+
include Template
|
7
|
+
|
8
|
+
def initialize(summaries, title, days, max_commits)
|
9
|
+
@summaries = summaries
|
10
|
+
@title = title
|
11
|
+
@days = days
|
12
|
+
@summary = Hash.new
|
13
|
+
@max_commits = max_commits
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate
|
17
|
+
report = ''
|
18
|
+
|
19
|
+
from = (Time.now - @days*60*60*24).strftime("%Y.%m.%d")
|
20
|
+
to = Time.now.strftime("%Y.%m.%d")
|
21
|
+
|
22
|
+
report << Template::HEAD.gsub('%TITLE%', @title).gsub("%FROM%", from).gsub('%TO%', to)
|
23
|
+
merge
|
24
|
+
|
25
|
+
for commit in @summary.keys.sort.reverse[0..@max_commits-1]
|
26
|
+
report << Template::COMMIT.gsub("%REPOSITORY%", @summary[commit][:repository] || "nil").
|
27
|
+
gsub("%MESSAGE%", @summary[commit][:message] || "nil").
|
28
|
+
gsub("%COMMITER%", @summary[commit][:commiter] || "nil").
|
29
|
+
gsub("%TIMEDATE%", @summary[commit][:time].to_s || "nil")
|
30
|
+
end
|
31
|
+
|
32
|
+
report << Template::TAIL
|
33
|
+
|
34
|
+
return report
|
35
|
+
end
|
36
|
+
|
37
|
+
def merge
|
38
|
+
# List all timestamps and sort
|
39
|
+
timestamps = []
|
40
|
+
for repository in @summaries.keys
|
41
|
+
for timestamp in @summaries[repository].keys
|
42
|
+
timestamps.push timestamp
|
43
|
+
end
|
44
|
+
end
|
45
|
+
timestamps.sort!
|
46
|
+
|
47
|
+
# Put commits from all repositories together, ordered by their timestamps
|
48
|
+
i = 0
|
49
|
+
for timestamp in timestamps
|
50
|
+
for repository in @summaries.keys
|
51
|
+
if (@summaries[repository][timestamp])
|
52
|
+
@summary[i] = Hash.new
|
53
|
+
@summary[i][:repository] = repository
|
54
|
+
@summary[i][:message] = @summaries[repository][timestamp][:message]
|
55
|
+
@summary[i][:commiter] = @summaries[repository][timestamp][:commiter]
|
56
|
+
@summary[i][:time] = @summaries[repository][timestamp][:time]
|
57
|
+
i = i + 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/lib/reporter.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'repository'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
class Reporter
|
5
|
+
attr_accessor :work_dir
|
6
|
+
attr_reader :repositories
|
7
|
+
attr_accessor :repository_stats, :commiter_stats, :repository_summaries
|
8
|
+
|
9
|
+
def initialize(work_dir)
|
10
|
+
@work_dir = work_dir
|
11
|
+
@repositories = Hash.new
|
12
|
+
@repository_stats = Hash.new
|
13
|
+
@commiter_stats = Hash.new
|
14
|
+
@repository_summaries = Hash.new
|
15
|
+
discover_repositories
|
16
|
+
initialize_repositories
|
17
|
+
end
|
18
|
+
|
19
|
+
def extract_stats(repository_name, from = Date.new, to = Date.new)
|
20
|
+
@repository_stats[repository_name] = Hash.new
|
21
|
+
repository = @repositories[repository_name]
|
22
|
+
repository.pull
|
23
|
+
repository.calculate_stats(from, to)
|
24
|
+
repository.generate_summary(from, to)
|
25
|
+
@repository_summaries[repository_name] = repository.summary
|
26
|
+
for commiter in repository.commiters.keys
|
27
|
+
@repository_stats[repository_name][commiter] = repository.commiters[commiter]
|
28
|
+
end
|
29
|
+
extract_stats_for_commiters(repository_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def extract_all_stats(from = Date.new, to = Date.new)
|
33
|
+
for repository in @repositories.values
|
34
|
+
yield repository.name if block_given?
|
35
|
+
extract_stats(repository.name, from, to)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def extract_stats_for_commiters(repository_name)
|
41
|
+
for commiter, lines in @repository_stats[repository_name]
|
42
|
+
@commiter_stats[commiter] = Hash.new unless @commiter_stats[commiter].instance_of? Hash
|
43
|
+
@commiter_stats[commiter][repository_name] = lines
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def discover_repositories
|
49
|
+
@repositories_names = `cd #{work_dir} && ls`.split("\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize_repositories
|
53
|
+
for repository_name in @repositories_names
|
54
|
+
repository = Repository.new(repository_name, @work_dir + "/#{repository_name}")
|
55
|
+
@repositories[repository_name] = repository
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/repository.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
class Repository
|
5
|
+
attr_accessor :name, :dir, :url
|
6
|
+
attr_reader :commiters, :summary
|
7
|
+
|
8
|
+
def initialize(name, dir)
|
9
|
+
@name = name
|
10
|
+
@dir = dir
|
11
|
+
@delimiter = "#{200.chr}@@@"
|
12
|
+
end
|
13
|
+
|
14
|
+
def clone
|
15
|
+
`cd #{dir} && git clone #{url} > /dev/null 2>&1`
|
16
|
+
end
|
17
|
+
|
18
|
+
def pull
|
19
|
+
`cd #{dir} && git pull`
|
20
|
+
end
|
21
|
+
|
22
|
+
def extract_log(from = Date.new, to = Date.new)
|
23
|
+
start_date = "#{Date.new - from} days ago"
|
24
|
+
end_date = "#{Date.new - to} days ago"
|
25
|
+
log = `cd #{dir} && git log --since="#{start_date}" --until="#{end_date} days ago" --pretty=tformat:"%n%an" --numstat --ignore-space-change`
|
26
|
+
return log
|
27
|
+
end
|
28
|
+
|
29
|
+
def extract_log_with_messages(from = Date.new, to = Date.new)
|
30
|
+
start_date = "#{Date.new - from} days ago"
|
31
|
+
end_date = "#{Date.new - to} days ago"
|
32
|
+
log = `cd #{dir} && git log --since="#{start_date}" --until="#{end_date} days ago" --pretty=tformat:"%an%n%at%n%s#{@delimiter}"`
|
33
|
+
return log
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_summary(from = Date.new, to = Date.new)
|
37
|
+
log = self.extract_log_with_messages(from, to)
|
38
|
+
@summary = Hash.new
|
39
|
+
for commit in log.split(@delimiter)
|
40
|
+
temp = []
|
41
|
+
for info in commit.split("\n")
|
42
|
+
temp.push info unless info == ""
|
43
|
+
end
|
44
|
+
@summary[temp[1]] = {:commiter => temp[0], :time => Time.at(temp[1].to_i), :message => temp[2]} if temp[1]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def calculate_stats(from = Date.new, to = Date.new)
|
49
|
+
regexp = Regexp.new('\A((\w+\s?)+)\s*((([\d-]+\s+[\d-]+.*)*\s)*)')
|
50
|
+
log = self.extract_log(from, to)
|
51
|
+
log[0] = '' unless log == ""
|
52
|
+
|
53
|
+
match = regexp.match(log)
|
54
|
+
@commiters = Hash.new
|
55
|
+
while !match.nil?
|
56
|
+
email = match[1].gsub("\n", "")
|
57
|
+
|
58
|
+
if @commiters[email].nil?
|
59
|
+
@commiters[email] = 0
|
60
|
+
end
|
61
|
+
|
62
|
+
commit_informations = match[3]
|
63
|
+
commit_informations.split("\n")
|
64
|
+
for commit_information in commit_informations
|
65
|
+
item = commit_information.split(/\s+/)
|
66
|
+
@commiters[email] += item[0].to_i + item[1].to_i
|
67
|
+
end
|
68
|
+
log.gsub!(regexp,"")
|
69
|
+
match = regexp.match(log)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/template.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module Template
|
2
|
+
|
3
|
+
HEAD = <<-HEADER
|
4
|
+
<html>
|
5
|
+
<head>
|
6
|
+
<title>%TITLE%</title>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<h2>%TITLE%</h2>
|
10
|
+
<p>From %FROM% to %TO%</p>
|
11
|
+
HEADER
|
12
|
+
|
13
|
+
TAIL = <<-TAIL
|
14
|
+
</body>
|
15
|
+
</html>
|
16
|
+
TAIL
|
17
|
+
|
18
|
+
MAJOR_HEAD = <<-MAJOR
|
19
|
+
<br>
|
20
|
+
<table border=1; width="600px">
|
21
|
+
<tr>
|
22
|
+
<td width="450px"><strong>%MAJOR%</strong></td>
|
23
|
+
<td width="150px"><strong>Lines</strong></td>
|
24
|
+
</tr>
|
25
|
+
MAJOR
|
26
|
+
|
27
|
+
MAJOR_TAIL = <<-MAJOR
|
28
|
+
</table>
|
29
|
+
MAJOR
|
30
|
+
|
31
|
+
MINOR = <<-MINOR
|
32
|
+
<tr>
|
33
|
+
<td>%MINOR%</td>
|
34
|
+
<td>%LINES%</td>
|
35
|
+
</tr>
|
36
|
+
MINOR
|
37
|
+
|
38
|
+
COMMIT = <<-COMMIT
|
39
|
+
<br>
|
40
|
+
<table border=1; width="600px">
|
41
|
+
<tr><td><strong>%REPOSITORY%</strong></td></tr>
|
42
|
+
<tr><td>%MESSAGE%</td></tr>
|
43
|
+
<tr><td><strong>by</strong> %COMMITER% <strong>at</strong> %TIMEDATE%</td></tr>
|
44
|
+
</table>
|
45
|
+
COMMIT
|
46
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
require 'repository'
|
4
|
+
require 'html_report'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
describe "HtmlReport" do
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
stats = Hash.new
|
11
|
+
stats['Major1'] = Hash.new
|
12
|
+
stats['Major1']['Minor1'] = 100
|
13
|
+
stats['Major1']['Minor2'] = 200
|
14
|
+
stats['Major2'] = Hash.new
|
15
|
+
stats['Major2']['Minor2'] = 222
|
16
|
+
stats['Major2']['Minor3'] = 333
|
17
|
+
@report = HtmlReport.new(stats, "Statistics for repositories!", 123).generate
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have a title" do
|
21
|
+
@report.should include("Statistics for repositories!")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should specify the considered date" do
|
25
|
+
from = (Time.now - 123*60*60*24).strftime("%Y.%m.%d")
|
26
|
+
to = Time.now.strftime("%Y.%m.%d")
|
27
|
+
@report.should include("From #{from} to #{to}")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should include all majors" do
|
31
|
+
@report.should include("Major1")
|
32
|
+
@report.should include("Major2")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should include all minors" do
|
36
|
+
@report.should include("Minor1")
|
37
|
+
@report.should include("Minor2")
|
38
|
+
@report.should include("Minor3")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should include the line impact for each minor in each major" do
|
42
|
+
@report.should include("100")
|
43
|
+
@report.should include("200")
|
44
|
+
@report.should include("222")
|
45
|
+
@report.should include("333")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should include the sum of all minors for each major" do
|
49
|
+
@report.should include("300")
|
50
|
+
@report.should include("555")
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
require 'repository'
|
4
|
+
require 'html_summary'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
describe "HtmlSummary" do
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
stats = Hash.new
|
11
|
+
stats['Repo1'] = Hash.new
|
12
|
+
stats['Repo1']['1'] = {:commiter => "Commiter 1", :time => "Time 1", :message => "Message 1"}
|
13
|
+
stats['Repo1']['3'] = {:commiter => "Commiter 2", :time => "Time 3", :message => "Message 3"}
|
14
|
+
stats['Repo1']['5'] = {:commiter => "Commiter 3", :time => "Time 5", :message => "Message 5"}
|
15
|
+
stats['Repo2'] = Hash.new
|
16
|
+
stats['Repo2']['2'] = {:commiter => "Commiter 3", :time => "Time 2", :message => "Message 2"}
|
17
|
+
stats['Repo2']['4'] = {:commiter => "Commiter 3", :time => "Time 4", :message => "Message 4"}
|
18
|
+
@report = HtmlSummary.new(stats, "Summary!", 123, 4).generate
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should have a title" do
|
22
|
+
@report.should include("Summary!")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should specify the considered date" do
|
26
|
+
from = (Time.now - 123*60*60*24).strftime("%Y.%m.%d")
|
27
|
+
to = Time.now.strftime("%Y.%m.%d")
|
28
|
+
@report.should include("From #{from} to #{to}")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should include the repository name" do
|
32
|
+
@report.should include("Repo1")
|
33
|
+
@report.should include("Repo2")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should include the commit message" do
|
37
|
+
@report.should_not include("Message 1")
|
38
|
+
@report.should include("Message 2")
|
39
|
+
@report.should include("Message 3")
|
40
|
+
@report.should include("Message 4")
|
41
|
+
@report.should include("Message 5")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should include commiter's name" do
|
45
|
+
@report.should_not include("Commiter 1")
|
46
|
+
@report.should include("Commiter 2")
|
47
|
+
@report.should include("Commiter 3")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should include the time and date for each commit" do
|
51
|
+
@report.should_not include("Time 1")
|
52
|
+
@report.should include("Time 2")
|
53
|
+
@report.should include("Time 3")
|
54
|
+
@report.should include("Time 4")
|
55
|
+
@report.should include("Time 5")
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
require 'repository'
|
4
|
+
|
5
|
+
describe "Repository" do
|
6
|
+
|
7
|
+
it "should calculate stats" do
|
8
|
+
log = "
|
9
|
+
User1
|
10
|
+
|
11
|
+
5 3 File1
|
12
|
+
2 2 File2
|
13
|
+
|
14
|
+
User1
|
15
|
+
|
16
|
+
1 1 File1
|
17
|
+
2 2 File3
|
18
|
+
|
19
|
+
User2
|
20
|
+
|
21
|
+
7 0 File1
|
22
|
+
0 3 File2
|
23
|
+
"
|
24
|
+
|
25
|
+
repository = Repository.new("SampleRepository","ArbitraryDirectory")
|
26
|
+
repository.stub(:extract_log).and_return(log)
|
27
|
+
repository.calculate_stats
|
28
|
+
repository.commiters['User1'].should be(18)
|
29
|
+
repository.commiters['User2'].should be(10)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should generate a summary" do
|
33
|
+
delimiter = "#{200.chr}@@@"
|
34
|
+
log = "User 1
|
35
|
+
12345
|
36
|
+
Message number 1#{delimiter}
|
37
|
+
User 2
|
38
|
+
12344
|
39
|
+
Message number 2#{delimiter}
|
40
|
+
"
|
41
|
+
repository = Repository.new("SampleRepository","ArbitraryDirectory")
|
42
|
+
repository.stub(:extract_log_with_messages).and_return(log)
|
43
|
+
repository.generate_summary
|
44
|
+
repository.summary['12345'][:commiter].should eql("User 1")
|
45
|
+
repository.summary['12345'][:time].should eql(Time.at(12345))
|
46
|
+
repository.summary['12345'][:message].should eql("Message number 1")
|
47
|
+
repository.summary['12344'][:commiter].should eql("User 2")
|
48
|
+
repository.summary['12344'][:time].should eql(Time.at(12344))
|
49
|
+
repository.summary['12344'][:message].should eql("Message number 2")
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: caelum-git-reports
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Caue Guerra
|
8
|
+
- Pedro Matiello
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-06-30 00:00:00 -07:00
|
14
|
+
default_executable: git-report.rb
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description:
|
18
|
+
email: caue.guerra@gmail.com
|
19
|
+
executables:
|
20
|
+
- git-report.rb
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files:
|
24
|
+
- LICENSE
|
25
|
+
- README.rdoc
|
26
|
+
files:
|
27
|
+
- .document
|
28
|
+
- .gitignore
|
29
|
+
- LICENSE
|
30
|
+
- README.rdoc
|
31
|
+
- Rakefile
|
32
|
+
- VERSION
|
33
|
+
- bin/git-report.rb
|
34
|
+
- lib/html_report.rb
|
35
|
+
- lib/html_summary.rb
|
36
|
+
- lib/reporter.rb
|
37
|
+
- lib/repository.rb
|
38
|
+
- lib/template.rb
|
39
|
+
- spec/html_report_spec.rb
|
40
|
+
- spec/html_summary_spec.rb
|
41
|
+
- spec/reporter_spec.rb
|
42
|
+
- spec/repository_spec.rb
|
43
|
+
- spec/spec_helper.rb
|
44
|
+
has_rdoc: false
|
45
|
+
homepage: http://github.com/caelum/git-reports
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --charset=UTF-8
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.2.0
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Git report tool
|
70
|
+
test_files:
|
71
|
+
- spec/html_report_spec.rb
|
72
|
+
- spec/html_summary_spec.rb
|
73
|
+
- spec/reporter_spec.rb
|
74
|
+
- spec/repository_spec.rb
|
75
|
+
- spec/spec_helper.rb
|