hubtime 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,174 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'thread'
4
+
5
+ module Hubtime
6
+ class Repo
7
+ attr_reader :cacher, :mutex, :thread_count
8
+ attr_reader :repo_name, :username, :start_time, :end_time
9
+ def initialize(repo_name, username, start_time, end_time)
10
+ @repo_name = repo_name
11
+ @username = username
12
+ @cacher = Cacher.new("#{repo_name}")
13
+ @mutex = Mutex.new
14
+ @thread_count = HubConfig.threads
15
+
16
+ if end_time < start_time
17
+ @start_time = end_time
18
+ @end_time = start_time
19
+ else
20
+ @start_time = start_time
21
+ @end_time = end_time
22
+ end
23
+ end
24
+
25
+ def auto_client
26
+ @auto_client ||= Octokit::Client.new(:login => HubConfig.user, :password => HubConfig.password, :auto_traversal => true)
27
+ end
28
+
29
+ def single_client
30
+ @single_client ||= Octokit::Client.new(:login => HubConfig.user, :password => HubConfig.password)
31
+ end
32
+
33
+ def commits(&block)
34
+ queue = self.sha_list.dup
35
+
36
+ if self.thread_count == 1
37
+ work_sha_queue(queue, block)
38
+ else
39
+ self.thread_count.times.map {
40
+ Thread.new do
41
+ work_sha_queue(queue, block)
42
+ end
43
+ }.each(&:join)
44
+ end
45
+
46
+ end
47
+
48
+ protected
49
+
50
+ def generate_sha_windows
51
+
52
+ diff = end_time.to_i - start_time.to_i
53
+ thread_time = diff / self.thread_count
54
+
55
+ # seeing this issue https://gist.github.com/4256275
56
+ # when fixed, we can bump these up and remove single_window_check
57
+ max_window_time = 3.days
58
+ min_window_time = 1.day
59
+
60
+ between = thread_time
61
+ between = max_window_time if between > max_window_time
62
+ between = min_window_time if between < min_window_time
63
+
64
+ windows = []
65
+ until_time = end_time
66
+ while until_time >= start_time
67
+ since_time = until_time - between
68
+ since_time = start_time if since_time < start_time
69
+
70
+ windows << [since_time, until_time]
71
+
72
+ until_time = since_time - 1.second
73
+ end
74
+
75
+ windows
76
+ end
77
+
78
+ def single_window_check
79
+ # pagination doesn't work, see if there are even 100 over the whole window
80
+ options = { :author => username }
81
+ options[:since] = start_time.iso8601
82
+ options[:until] = end_time.iso8601
83
+ options[:per_page] = 100
84
+ options[:page] = 1
85
+
86
+ commits = single_client.commits(repo_name, "master", options)
87
+ return if commits.size >= 100 # go slower
88
+
89
+ result = []
90
+ commits.each do |hash|
91
+ next unless hash.is_a?(Hashie::Mash)
92
+ next unless hash.sha
93
+ result << hash.sha
94
+ end
95
+
96
+ result
97
+ end
98
+
99
+ def sha_list
100
+ cache_key = "#{username}/#{start_time.to_i}-#{end_time.to_i}"
101
+ # puts "sha_list: #{cache_key}\n"
102
+ if cached = cacher.read(cache_key)
103
+ return cached
104
+ end
105
+
106
+ result = single_window_check
107
+
108
+ if result.nil?
109
+ queue = self.generate_sha_windows
110
+ result = []
111
+
112
+ if self.thread_count == 1
113
+ work_window_queue(queue, result)
114
+ else
115
+ self.thread_count.times.map {
116
+ Thread.new do
117
+ work_window_queue(queue, result)
118
+ end
119
+ }.each(&:join)
120
+ end
121
+ end
122
+
123
+ cacher.write(cache_key, result)
124
+ end
125
+
126
+ def work_window_queue(queue, result)
127
+ while window = mutex.synchronize { queue.shift }
128
+ since_time, until_time = window
129
+ list = commits_window(since_time, until_time)
130
+ mutex.synchronize { result.concat list }
131
+ end
132
+ end
133
+
134
+ def commits_window(since_time, until_time)
135
+ cache_key = "#{username}/#{since_time.to_i}-#{until_time.to_i}"
136
+ #puts "commits_window: #{cache_key}\n"
137
+ if cached = cacher.read(cache_key)
138
+ return cached
139
+ end
140
+
141
+ options = { :author => username }
142
+ options[:since] = since_time.iso8601
143
+ options[:until] = until_time.iso8601
144
+
145
+ result = []
146
+ commits = auto_client.commits(repo_name, "master", options)
147
+ commits.each do |hash|
148
+ next unless hash.is_a?(Hashie::Mash)
149
+ next unless hash.sha
150
+ result << hash.sha
151
+ end
152
+
153
+ cacher.write(cache_key, result.uniq)
154
+ end
155
+
156
+ def work_sha_queue(queue, block)
157
+ while sha = mutex.synchronize { queue.shift }
158
+ hash = fetch_sha(sha)
159
+ next unless hash.is_a?(Hashie::Mash)
160
+ next unless hash.sha
161
+ commit = Commit.new(hash, repo_name, username)
162
+ mutex.synchronize { block.call commit }
163
+ end
164
+ end
165
+
166
+ def fetch_sha(sha)
167
+ cache_key = "shas/#{sha}"
168
+ hashie = cacher.read(cache_key)
169
+ return hashie if hashie
170
+ hashie = single_client.commit(repo_name, sha)
171
+ cacher.write(cache_key, hashie)
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,3 @@
1
+ module Hubtime
2
+ VERSION = '0.0.1'
3
+ end
data/readme/graph.png ADDED
Binary file
data/readme/impact.png ADDED
Binary file
data/readme/pie.png ADDED
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,196 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hubtime
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brian Leonard
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: active_support
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: commander
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '4.1'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '4.1'
46
+ - !ruby/object:Gem::Dependency
47
+ name: i18n
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '0.6'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.6'
62
+ - !ruby/object:Gem::Dependency
63
+ name: tzinfo
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '0.3'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '0.3'
78
+ - !ruby/object:Gem::Dependency
79
+ name: octokit
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '1.20'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '1.20'
94
+ - !ruby/object:Gem::Dependency
95
+ name: terminal-table
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '1.4'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '1.4'
110
+ - !ruby/object:Gem::Dependency
111
+ name: erubis
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '2.7'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '2.7'
126
+ - !ruby/object:Gem::Dependency
127
+ name: hashie
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: '1.2'
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: '1.2'
142
+ description: Visualization of your Github activity over the past year via Github API
143
+ with visualizations like table, graph, stacked graph and pie chart.
144
+ email: contact@plataformatec.com.br
145
+ executables:
146
+ - hubtime
147
+ extensions: []
148
+ extra_rdoc_files: []
149
+ files:
150
+ - .gitignore
151
+ - Gemfile
152
+ - Gemfile.lock
153
+ - MIT-LICENSE
154
+ - README.md
155
+ - bin/hubtime
156
+ - hubtime.gemspec
157
+ - lib/hubtime.rb
158
+ - lib/hubtime/activity.rb
159
+ - lib/hubtime/cacher.rb
160
+ - lib/hubtime/charts/graph.erb
161
+ - lib/hubtime/charts/impact.erb
162
+ - lib/hubtime/charts/pie.erb
163
+ - lib/hubtime/commit.rb
164
+ - lib/hubtime/github.rb
165
+ - lib/hubtime/hub_config.rb
166
+ - lib/hubtime/repo.rb
167
+ - lib/hubtime/version.rb
168
+ - readme/graph.png
169
+ - readme/impact.png
170
+ - readme/pie.png
171
+ - readme/stacked.png
172
+ homepage: http://github.com/bleonard/hubtime
173
+ licenses: []
174
+ post_install_message:
175
+ rdoc_options: []
176
+ require_paths:
177
+ - lib
178
+ required_ruby_version: !ruby/object:Gem::Requirement
179
+ none: false
180
+ requirements:
181
+ - - ! '>='
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ requirements: []
191
+ rubyforge_project: hubtime
192
+ rubygems_version: 1.8.24
193
+ signing_key:
194
+ specification_version: 3
195
+ summary: Visualization of your Github activity over the past year via Github API.
196
+ test_files: []