gitchart 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2008 Hans Engel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ =begin
2
+ Copyright (c) 2008 Hans Engel
3
+ See the file LICENSE for licensing details.
4
+ =end
5
+
6
+ require 'rubygems'
7
+ Gem::manage_gems
8
+ require 'rake/gempackagetask'
9
+
10
+ spec = eval(File.read('gitchart.gemspec'))
11
+
12
+ Rake::GemPackageTask.new(spec) do |pkg|
13
+ pkg.need_tar = true
14
+ end
15
+
16
+ task :default => "pkg/#{spec.name}-#{spec.version}.gem" do
17
+ puts 'generated latest version'
18
+ end
19
+
20
+ desc "build 'n' install"
21
+ task :bni => "pkg/#{spec.name}-#{spec.version}.gem" do
22
+ puts `sudo gem install pkg/#{spec.name}-#{spec.version}.gem`
23
+ end
data/bin/git-chart ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby -s
2
+
3
+ =begin
4
+ Copyright (c) 2008 Hans Engel
5
+ See the file LICENSE for licensing details.
6
+ =end
7
+
8
+ begin; require 'rubygems'; rescue LoadError; end
9
+ require 'gitchart'
10
+
11
+ repo = '.'
12
+ branch = 'master'
13
+ size = '1000x300'
14
+ threed = true
15
+
16
+ repo = ARGV[0] if ARGV[0]
17
+ branch = ARGV[1] if ARGV[1]
18
+ size = ARGV[2] if ARGV[2]
19
+
20
+ if ARGV[3]
21
+ threed = case ARGV[3]
22
+ when 'true': true
23
+ when 'false': false
24
+ end
25
+ end
26
+
27
+ gc = GitChart.new size, threed, repo, branch
28
+ gc.run
data/gitchart.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ =begin
2
+ Copyright (c) 2008 Hans Engel
3
+ See the file LICENSE for licensing details.
4
+ =end
5
+
6
+ Gem::Specification.new do |s|
7
+ s.platform = Gem::Platform::RUBY
8
+ s.name = 'gitchart'
9
+ s.version = '1.0'
10
+ s.date = '2008-08-23'
11
+ s.homepage = 'http://github.com/hans/gitchart'
12
+ s.author = 'Hans Engel'
13
+ s.email = 'spam.me@engel.uk.to'
14
+ s.summary = 'Generate cool stats about Git repositories'
15
+ s.files = [
16
+ 'LICENSE',
17
+ 'Rakefile',
18
+ 'gitchart.gemspec',
19
+ 'lib/gitchart.rb',
20
+ 'lib/platform.rb',
21
+ 'bin/git-chart']
22
+ s.bindir = 'bin'
23
+ s.executables = ['git-chart']
24
+ s.require_paths = ['lib']
25
+ s.add_dependency('gchartrb', '>= 0.8')
26
+ s.add_dependency('schacon-grit', '>= 0.9.3')
27
+ end
data/lib/gitchart.rb ADDED
@@ -0,0 +1,261 @@
1
+ =begin
2
+ Copyright (c) 2008 Hans Engel
3
+ See the file LICENSE for licensing details.
4
+ =end
5
+
6
+ require 'ftools'
7
+ require 'tempfile'
8
+
9
+ require 'platform'
10
+ require 'google_chart'
11
+ include GoogleChart
12
+ require 'grit'
13
+ include Grit
14
+
15
+ class GitChart
16
+ def initialize(size = '1000x300', threed = true, repo = '.', branch = 'master')
17
+ begin
18
+ @repo = Repo.new(repo)
19
+ rescue
20
+ raise "Could not initialize Grit instance."
21
+ end
22
+ @size = size
23
+ @threed = threed
24
+ @branch = branch
25
+ @files = 0
26
+ if repo == '.'
27
+ rpath = Dir.getwd
28
+ else
29
+ rpath = repo
30
+ end
31
+ @html = <<EOF
32
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
33
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
34
+ <html xmlns="http://www.w3.org/1999/xhtml">
35
+ <head profile="http://purl.org/uF/2008/03">
36
+ <meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
37
+ <style type="text/css">
38
+ * { margin: 0; padding: 0; }
39
+ body { width: 1000px; margin: 50px auto; overflow: auto; text-align: center; font-size: 13px; }
40
+ h1 { font-weight: normal; font-size: 20px; }
41
+ table { border: none; margin: 20px auto; width: 500px; }
42
+ tr { border: none; }
43
+ td { border: none; padding: 7px; }
44
+ td.key { background-color: #c7e4e5; width: 145px; font-weight: bold; font-size: 11px; }
45
+ </style>
46
+ <title>gitchart output</title>
47
+ </head>
48
+ <body>
49
+ <h1>Git Repository Stats</h1>
50
+ <p>These stats were generated by <a href="http://github.com/hans/git-chart"><code>git-chart</code></a>.
51
+ <table cellpadding="0" cellspacing="0">
52
+ <tr>
53
+ <td class="key">repository location:</td>
54
+ <td>#{rpath}</td>
55
+ </tr>
56
+ <tr>
57
+ <td class="key">generated on:</td>
58
+ <td>#{Time.now.to_s}</td>
59
+ </tr>
60
+ </table>
61
+
62
+ EOF
63
+ end
64
+
65
+ def run
66
+ puts "Generating chart data . . ."
67
+ puts "This may take a while, depending on the size of your repository."
68
+ begin
69
+ @commits = @repo.commits_since @branch
70
+ rescue SystemStackError
71
+ puts "Uh oh, your repository is humongous. We're going to have to only grab stats for the last several hundred."
72
+ puts "How many commits should be graphed? (750 is probably as far as you can get). "
73
+ amt = gets
74
+ @commits = @repo.commits @branch, amt.strip.to_i
75
+ end
76
+ chart_authors
77
+ chart_commits :bar
78
+ chart_commits :line
79
+ chart_hours
80
+ chart_extensions
81
+ chart_bytes
82
+ chart_awesomeness
83
+ output
84
+ end
85
+
86
+ def chart_authors
87
+ generating_chart 'Repository Authors'
88
+ authors = {}
89
+ @commits.each do |c|
90
+ puts "\treading commit #{c.id[0, 7]}" if $vv
91
+ if authors[c.author.to_s]
92
+ authors[c.author.to_s] += 1
93
+ else
94
+ authors[c.author.to_s] = 1
95
+ puts "\t\tauthor: #{c.author.to_s}" if $v or $vv
96
+ end
97
+ end
98
+ PieChart.new(@size, 'Repository Authors', @threed) do |pc|
99
+ authors.each do |a, num|
100
+ pc.data a, num
101
+ end
102
+ @html += "<img src='#{pc.to_url}' alt='Repository Authors' /><br/>"
103
+ end
104
+ end
105
+
106
+ def chart_commits(type)
107
+ generating_chart 'Commit Frequency'
108
+ weeks = Array.new 53, 0
109
+ @commits.each do |c|
110
+ puts "\treading commit #{c.id[0, 7]}" if $vv
111
+ time = Time.parse c.committed_date.to_s
112
+ week = time.strftime '%U'
113
+ weeks[week.to_i] ||= 0
114
+ weeks[week.to_i] += 1
115
+ end
116
+ case type
117
+ when :bar:
118
+ BarChart.new(@size, 'Commit Frequency', :vertical, @threed) do |bc|
119
+ bc.data 'Commits', weeks
120
+ bc.axis :y, { :range => [0, weeks.max] }
121
+ @html += "<img src='#{bc.to_url}' alt='Commit Frequency' /><br/>"
122
+ end
123
+ when :line:
124
+ weeks.pop while weeks.last.zero?
125
+ LineChart.new @size, 'Commit Frequency' do |lc|
126
+ lc.data 'Commits', weeks
127
+ lc.axis :y, { :range => [0, weeks.max] }
128
+ @html += "<img src='#{lc.to_url}' alt='Commit Frequency' /><br/>"
129
+ end
130
+ end
131
+ end
132
+
133
+ def chart_hours
134
+ generating_chart 'Commit Hours'
135
+ hours = Hash.new
136
+ @commits.each do |c|
137
+ puts "\treading commit #{c.id[0, 7]}" if $vv
138
+ date = Time.parse c.committed_date.to_s
139
+ hour = date.strftime '%H'
140
+ hours[hour.to_i] ||= 0
141
+ hours[hour.to_i] += 1
142
+ end
143
+ PieChart.new(@size, 'Commit Hours', @threed) do |pc|
144
+ hours.each do |hr, num|
145
+ pc.data hr.to_s + ':00 - ' + hr.to_s + ':59', num
146
+ end
147
+ @html += "<img src='#{pc.to_url}' alt='Commit Hours' /><br/>"
148
+ end
149
+ end
150
+
151
+ def chart_extensions
152
+ generating_chart 'Popular Extensions'
153
+ @extensions = {}
154
+ @tree = @commits.first.tree
155
+ extensions_add_tree @tree
156
+ if $v or $vv
157
+ print "\textensions: "
158
+ p @extensions
159
+ end
160
+ PieChart.new(@size, 'Popular Extensions', @threed) do |pc|
161
+ @extensions.each do |ext, num|
162
+ pc.data ext, num
163
+ end
164
+ @html += "<img src='#{pc.to_url}' alt='Popular Extensions' /><br/>"
165
+ end
166
+ end
167
+ def extensions_add_tree(tree)
168
+ tree.contents.each do |el|
169
+ if Blob === el
170
+ extensions_add_blob el
171
+ elsif Tree === el
172
+ extensions_add_tree el
173
+ end
174
+ end
175
+ end
176
+ def extensions_add_blob(el)
177
+ ext = File.extname el.name
178
+ if ext == ''
179
+ @extensions['Other'] += 1 rescue @extensions['Other'] = 1
180
+ else
181
+ @extensions[ext] += 1 rescue @extensions[ext] = 1
182
+ end
183
+ @files += 1
184
+ end
185
+
186
+ def chart_bytes
187
+ generating_chart 'Total Filesize'
188
+ @bytes = Array.new
189
+ @commits.each do |c|
190
+ print "\treading commit #{c.id[0, 7]}" if $vv
191
+ @bytes.push 0
192
+ bytes_add_tree c.tree
193
+ puts " (#{@bytes.last} bytes)" if $vv
194
+ end
195
+ @bytes = @bytes.reverse
196
+ LineChart.new(@size, 'Total Filesize') do |lc|
197
+ lc.data 'Bytes', @bytes
198
+ lc.axis :y, { :range => [0, @bytes.max] }
199
+ @html += "<img src='#{lc.to_url}' alt='Total Filesize' /><br/>"
200
+ end
201
+ end
202
+ def bytes_add_tree(tree)
203
+ tree.contents.each do |el|
204
+ if Blob === el
205
+ bytes_add_blob el
206
+ elsif Tree === el
207
+ bytes_add_tree el
208
+ end
209
+ end
210
+ end
211
+ def bytes_add_blob(blob)
212
+ bytes = blob.size
213
+ @bytes[-1] += bytes
214
+ end
215
+
216
+ def chart_awesomeness
217
+ generating_chart 'Repository Awesomeness'
218
+ @extensions['.rb'] ||= 0.1
219
+ awesomeness = @files / @extensions['.rb']
220
+ awesomeness = ( awesomeness * 100 ).round / 100.0
221
+ awesomeness = 0.1 if @extensions['.rb'] == 0.1
222
+ puts "\tawesomeness: #{awesomeness}%" if $v or $vv
223
+ url = "http://chart.apis.google.com/chart?cht=gom&chtt=Repository+Awesomeness&chs=#{@size}&chl=#{awesomeness}%25&chd=t:#{awesomeness}"
224
+ @html += "<img src='#{url}' alt='Repository Awesomeness' /><br/><br/>"
225
+ end
226
+
227
+ def generating_chart(chart)
228
+ puts "Generating chart '#{chart}' . . ."
229
+ end
230
+
231
+ def output
232
+ @html += <<EOF
233
+ </body>
234
+ </html>
235
+ EOF
236
+ t = Tempfile.new 'gitchart-' + Time.now.to_i.to_s
237
+ t.print @html
238
+ t.flush
239
+ f = t.path + '.html'
240
+ File.move t.path, f
241
+ program = ''
242
+ case Platform::OS
243
+ when :unix:
244
+ if Platform::IMPL == :macosx
245
+ print "determined that platform = osx" if $v or $vv
246
+ program = 'open'
247
+ `open #{f}`
248
+ else
249
+ print "determined that platform = unix" if $v or $vv
250
+ program = 'xdg-open'
251
+ `xdg-open #{f}`
252
+ end
253
+ when :win32:
254
+ print "determined that platform = win32" if $v or $vv
255
+ program = 'start'
256
+ `start #{f}`
257
+ end
258
+ puts ". . . using `#{program}` to open the HTML page" if $v or $vv
259
+ puts "final file path: " + f if $v or $vv
260
+ end
261
+ end
data/lib/platform.rb ADDED
@@ -0,0 +1,101 @@
1
+ #
2
+ # platform.rb: naive platform detection for Ruby
3
+ # author: Matt Mower <self@mattmower.com>
4
+ #
5
+
6
+ # == Platform
7
+ #
8
+ # Platform is a simple module which parses the Ruby constant
9
+ # RUBY_PLATFORM and works out the OS, it's implementation,
10
+ # and the architecture it's running on.
11
+ #
12
+ # The motivation for writing this was coming across a case where
13
+ #
14
+ # +if RUBY_PLATFORM =~ /win/+
15
+ #
16
+ # didn't behave as expected (i.e. on powerpc-darwin-8.1.0)
17
+ #
18
+ # It is hoped that providing a library for parsing the platform
19
+ # means that we can cover all the cases and have something which
20
+ # works reliably 99% of the time.
21
+ #
22
+ # Please report any anomalies or new combinations to the author(s).
23
+ #
24
+ # == Use
25
+ #
26
+ # require "platform"
27
+ #
28
+ # defines
29
+ #
30
+ # Platform::OS (:unix,:win32,:vms,:os2)
31
+ # Platform::IMPL (:macosx,:linux,:mswin)
32
+ # Platform::ARCH (:powerpc,:x86,:alpha)
33
+ #
34
+ # if an unknown configuration is encountered any (or all) of
35
+ # these constant may have the value :unknown.
36
+ #
37
+ # To display the combination for your setup run
38
+ #
39
+ # ruby platform.rb
40
+ #
41
+ module Platform
42
+
43
+ if RUBY_PLATFORM =~ /darwin/i
44
+ OS = :unix
45
+ IMPL = :macosx
46
+ elsif RUBY_PLATFORM =~ /linux/i
47
+ OS = :unix
48
+ IMPL = :linux
49
+ elsif RUBY_PLATFORM =~ /freebsd/i
50
+ OS = :unix
51
+ IMPL = :freebsd
52
+ elsif RUBY_PLATFORM =~ /netbsd/i
53
+ OS = :unix
54
+ IMPL = :netbsd
55
+ elsif RUBY_PLATFORM =~ /mswin/i
56
+ OS = :win32
57
+ IMPL = :mswin
58
+ elsif RUBY_PLATFORM =~ /cygwin/i
59
+ OS = :unix
60
+ IMPL = :cygwin
61
+ elsif RUBY_PLATFORM =~ /mingw/i
62
+ OS = :win32
63
+ IMPL = :mingw
64
+ elsif RUBY_PLATFORM =~ /bccwin/i
65
+ OS = :win32
66
+ IMPL = :bccwin
67
+ elsif RUBY_PLATFORM =~ /wince/i
68
+ OS = :win32
69
+ IMPL = :wince
70
+ elsif RUBY_PLATFORM =~ /vms/i
71
+ OS = :vms
72
+ IMPL = :vms
73
+ elsif RUBY_PLATFORM =~ /os2/i
74
+ OS = :os2
75
+ IMPL = :os2 # maybe there is some better choice here?
76
+ else
77
+ OS = :unknown
78
+ IMPL = :unknown
79
+ end
80
+
81
+ # whither AIX, SOLARIS, and the other unixen?
82
+
83
+ if RUBY_PLATFORM =~ /(i\d86)/i
84
+ ARCH = :x86
85
+ elsif RUBY_PLATFORM =~ /ia64/i
86
+ ARCH = :ia64
87
+ elsif RUBY_PLATFORM =~ /powerpc/i
88
+ ARCH = :powerpc
89
+ elsif RUBY_PLATFORM =~ /alpha/i
90
+ ARCH = :alpha
91
+ else
92
+ ARCH = :unknown
93
+ end
94
+
95
+ # What about AMD, Turion, Motorola, etc..?
96
+
97
+ end
98
+
99
+ if __FILE__ == $0
100
+ puts "Platform OS=#{Platform::OS}, IMPL=#{Platform::IMPL}, ARCH=#{Platform::ARCH}"
101
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gitchart
3
+ version: !ruby/object:Gem::Version
4
+ version: "1.0"
5
+ platform: ruby
6
+ authors:
7
+ - Hans Engel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-23 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: gchartrb
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0.8"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: schacon-grit
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.3
34
+ version:
35
+ description:
36
+ email: spam.me@engel.uk.to
37
+ executables:
38
+ - git-chart
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - LICENSE
45
+ - Rakefile
46
+ - gitchart.gemspec
47
+ - lib/gitchart.rb
48
+ - lib/platform.rb
49
+ - bin/git-chart
50
+ has_rdoc: false
51
+ homepage: http://github.com/hans/gitchart
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.2.0
73
+ signing_key:
74
+ specification_version: 2
75
+ summary: Generate cool stats about Git repositories
76
+ test_files: []
77
+