caelum-git_reports 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/git_reports.gemspec +59 -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 +76 -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/git_reports.gemspec
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{git_reports}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Caue Guerra", "Pedro Matiello"]
|
9
|
+
s.date = %q{2009-06-30}
|
10
|
+
s.default_executable = %q{git-report.rb}
|
11
|
+
s.email = %q{caue.guerra@gmail.com}
|
12
|
+
s.executables = ["git-report.rb"]
|
13
|
+
s.extra_rdoc_files = [
|
14
|
+
"LICENSE",
|
15
|
+
"README.rdoc"
|
16
|
+
]
|
17
|
+
s.files = [
|
18
|
+
".document",
|
19
|
+
".gitignore",
|
20
|
+
"LICENSE",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"bin/git-report.rb",
|
25
|
+
"git_reports.gemspec",
|
26
|
+
"lib/html_report.rb",
|
27
|
+
"lib/html_summary.rb",
|
28
|
+
"lib/reporter.rb",
|
29
|
+
"lib/repository.rb",
|
30
|
+
"lib/template.rb",
|
31
|
+
"spec/html_report_spec.rb",
|
32
|
+
"spec/html_summary_spec.rb",
|
33
|
+
"spec/reporter_spec.rb",
|
34
|
+
"spec/repository_spec.rb",
|
35
|
+
"spec/spec_helper.rb"
|
36
|
+
]
|
37
|
+
s.homepage = %q{http://github.com/caelum/git-reports}
|
38
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubygems_version = %q{1.3.3}
|
41
|
+
s.summary = %q{Git report tool}
|
42
|
+
s.test_files = [
|
43
|
+
"spec/html_report_spec.rb",
|
44
|
+
"spec/html_summary_spec.rb",
|
45
|
+
"spec/reporter_spec.rb",
|
46
|
+
"spec/repository_spec.rb",
|
47
|
+
"spec/spec_helper.rb"
|
48
|
+
]
|
49
|
+
|
50
|
+
if s.respond_to? :specification_version then
|
51
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
52
|
+
s.specification_version = 3
|
53
|
+
|
54
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
55
|
+
else
|
56
|
+
end
|
57
|
+
else
|
58
|
+
end
|
59
|
+
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,76 @@
|
|
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
|
+
- git_reports.gemspec
|
35
|
+
- lib/html_report.rb
|
36
|
+
- lib/html_summary.rb
|
37
|
+
- lib/reporter.rb
|
38
|
+
- lib/repository.rb
|
39
|
+
- lib/template.rb
|
40
|
+
- spec/html_report_spec.rb
|
41
|
+
- spec/html_summary_spec.rb
|
42
|
+
- spec/reporter_spec.rb
|
43
|
+
- spec/repository_spec.rb
|
44
|
+
- spec/spec_helper.rb
|
45
|
+
has_rdoc: false
|
46
|
+
homepage: http://github.com/caelum/git-reports
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options:
|
49
|
+
- --charset=UTF-8
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.2.0
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Git report tool
|
71
|
+
test_files:
|
72
|
+
- spec/html_report_spec.rb
|
73
|
+
- spec/html_summary_spec.rb
|
74
|
+
- spec/reporter_spec.rb
|
75
|
+
- spec/repository_spec.rb
|
76
|
+
- spec/spec_helper.rb
|