hubba 0.1.2 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4a82adab1dd587bb3d9604b7ca60737747fe22f9
4
- data.tar.gz: 637d4e8a7714b3a6868e070cd064ed7a9f27d233
3
+ metadata.gz: 84577f7d76ee6b6e2b0c1dd2c747536bede539fe
4
+ data.tar.gz: 9f42b72e4402d148eaccbfd635f316161a50a857
5
5
  SHA512:
6
- metadata.gz: 2cef2397c74486671a6ac559e5ebe89dfe7d98efefe025c5f68694cbaa8809de279efe6bbc3aa7388426b01c198aea81214147a1f3d568ac8652d730a041e75f
7
- data.tar.gz: d5b460db26d282e941292bc7c1d030a7ee9b3d98502a39f12f659517a744f55913c85f7dc5b093d9494e7124ff7ba0ba17e9406805ccfab0a8ec82c55dc9be33
6
+ metadata.gz: 94e26559d4d814411a5537f879f58132c906ef7a3b2f7a61cc8f83d0e5f282b143d68f37a5462e5aef5e25daa86072b40e94c1b5177ab57023b80260f503b054
7
+ data.tar.gz: b9f03dba1f8861edbec94fb3411b2383dc1e12744387b9c6480b43a75ee6fa7331b57d81199a084cec742f0b35abf09167409d0328fd00a7da4fe3f15343a167
File without changes
@@ -1,4 +1,4 @@
1
- HISTORY.md
1
+ CHANGELOG.md
2
2
  Manifest.txt
3
3
  README.md
4
4
  Rakefile
@@ -6,9 +6,16 @@ lib/hubba.rb
6
6
  lib/hubba/cache.rb
7
7
  lib/hubba/client.rb
8
8
  lib/hubba/github.rb
9
+ lib/hubba/stats.rb
9
10
  lib/hubba/version.rb
10
11
  test/cache/users~geraldb~orgs.json
11
12
  test/cache/users~geraldb~repos.json
12
13
  test/helper.rb
14
+ test/stats/jekyll~minima.json
15
+ test/stats/openblockchains~awesome-blockchains.json
16
+ test/stats/opendatajson~factbook.json.json
17
+ test/stats/poole~hyde.json
13
18
  test/test_cache.rb
14
19
  test/test_config.rb
20
+ test/test_stats.rb
21
+ test/test_stats_tmp.rb
data/README.md CHANGED
@@ -1,20 +1,20 @@
1
- # hubba
2
-
3
- hubba gem - (yet) another (lite) GitHub HTTP API client / library
4
-
5
- * home :: [github.com/rubylibs/hubba](https://github.com/rubylibs/hubba)
6
- * bugs :: [github.com/rubylibs/hubba/issues](https://github.com/rubylibs/hubba/issues)
7
- * gem :: [rubygems.org/gems/hubba](https://rubygems.org/gems/hubba)
8
- * rdoc :: [rubydoc.info/gems/hubba](http://rubydoc.info/gems/hubba)
9
-
10
-
11
- ## Usage
12
-
13
- TBD
14
-
15
-
16
- ## License
17
-
18
- The `hubba` scripts are dedicated to the public domain.
19
- Use it as you please with no restrictions whatsoever.
20
-
1
+ # hubba
2
+
3
+ hubba gem - (yet) another (lite) GitHub HTTP API client / library
4
+
5
+ * home :: [github.com/rubycoco/git](https://github.com/rubycoco/git)
6
+ * bugs :: [github.com/rubycoco/git/issues](https://github.com/rubycoco/git/issues)
7
+ * gem :: [rubygems.org/gems/hubba](https://rubygems.org/gems/hubba)
8
+ * rdoc :: [rubydoc.info/gems/hubba](http://rubydoc.info/gems/hubba)
9
+
10
+
11
+ ## Usage
12
+
13
+ TBD
14
+
15
+
16
+
17
+ ## License
18
+
19
+ The `hubba` scripts are dedicated to the public domain.
20
+ Use it as you please with no restrictions whatsoever.
data/Rakefile CHANGED
@@ -5,26 +5,26 @@ Hoe.spec 'hubba' do
5
5
 
6
6
  self.version = Hubba::VERSION
7
7
 
8
- self.summary = 'hubba - (yet) another (lite) GitHub HTTP API client / library'
8
+ self.summary = 'hubba - (yet) another (lite) GitHub HTTP API client / library'
9
9
  self.description = summary
10
10
 
11
- self.urls = ['https://github.com/rubylibs/hubba']
11
+ self.urls = { home: 'https://github.com/rubycoco/git' }
12
12
 
13
13
  self.author = 'Gerald Bauer'
14
14
  self.email = 'ruby-talk@ruby-lang.org'
15
15
 
16
16
  # switch extension to .markdown for gihub formatting
17
17
  self.readme_file = 'README.md'
18
- self.history_file = 'HISTORY.md'
18
+ self.history_file = 'CHANGELOG.md'
19
19
 
20
20
  self.extra_deps = [
21
- ['logutils' ],
21
+ ['webclient', '>= 0.1.1']
22
22
  ]
23
23
 
24
24
  self.licenses = ['Public Domain']
25
25
 
26
26
  self.spec_extras = {
27
- required_ruby_version: '>= 1.9.2'
27
+ required_ruby_version: '>= 2.2.2'
28
28
  }
29
29
 
30
30
  end
@@ -1,23 +1,13 @@
1
- # encoding: utf-8
2
-
3
- require 'net/http'
4
- require "net/https"
5
- require 'uri'
6
-
7
- require 'pp'
8
- require 'json'
9
- require 'yaml'
10
-
11
-
12
- # 3rd party gems/libs
13
- require 'logutils'
1
+ # 3rd party (our own)
2
+ require 'webclient'
14
3
 
15
4
  # our own code
16
5
  require 'hubba/version' # note: let version always go first
17
6
  require 'hubba/cache'
18
7
  require 'hubba/client'
19
8
  require 'hubba/github'
9
+ require 'hubba/stats'
20
10
 
21
11
 
22
12
  # say hello
23
- puts Hubba.banner if defined?($RUBYLIBS_DEBUG)
13
+ puts Hubba.banner if defined?($RUBYCOCO_DEBUG)
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Hubba
4
2
 
5
3
  class Cache ## lets you work with GitHub api "offline" using just a local cache of stored json
@@ -14,7 +12,7 @@ class Cache ## lets you work with GitHub api "offline" using just a local ca
14
12
  basename = request_uri_to_basename( request_uri )
15
13
  path = "#{@dir}/#{basename}.json"
16
14
  if File.exist?( path )
17
- text = File.read( path ) ## todo/fix: use File.read_utf8
15
+ text = File.open( path, 'r:utf-8') { |f| f.read }
18
16
  json = JSON.parse( text )
19
17
  json
20
18
  else
@@ -32,8 +30,8 @@ class Cache ## lets you work with GitHub api "offline" using just a local ca
32
30
  data = obj # assume Hash or Array -- todo: add support for String - why? why not??
33
31
  end
34
32
 
35
- File.open( path, 'w' ) do |f|
36
- f.write JSON.pretty_generate( data )
33
+ File.open( path, 'w:utf-8' ) do |f|
34
+ f.write( JSON.pretty_generate( data ))
37
35
  end
38
36
  end
39
37
 
@@ -42,6 +40,7 @@ class Cache ## lets you work with GitHub api "offline" using just a local ca
42
40
  ## 1) cut off leading /
43
41
  ## 2) convert / to ~
44
42
  ## 3) remove (optional) query string (for now) - why? why not?
43
+ ## e.g. /users/#{name}/orgs?per_page=100 or such
45
44
  ##
46
45
  ## e.g.
47
46
  ## '/users/geraldb' => 'users~geraldb',
@@ -1,53 +1,76 @@
1
- # encoding: utf-8
2
-
3
1
  module Hubba
4
2
 
5
3
 
6
4
  class Client
7
5
 
8
- def initialize( user: nil, password: nil )
9
- uri = URI.parse( "https://api.github.com" )
10
- @http = Net::HTTP.new(uri.host, uri.port)
11
- @http.use_ssl = true
12
- @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
6
+ BASE_URL = 'https://api.github.com'
7
+
8
+
9
+ def initialize( token: nil,
10
+ user: nil, password: nil )
11
+ ## add support for (personal access) token
12
+ @token = token
13
13
 
14
14
  ## add support for basic auth - defaults to no auth (nil/nil)
15
+ ## remove - deprecated (use token) - why? why not?
15
16
  @user = user ## use login like Oktokit - why? why not?
16
17
  @password = password
17
18
  end # method initialize
18
19
 
20
+
21
+
19
22
  def get( request_uri )
23
+ ###
24
+ # e.g. /users/geraldb
25
+ # /users/geraldb/repos
26
+
20
27
  puts "GET #{request_uri}"
28
+ url = "#{BASE_URL}/#{request_uri}"
21
29
 
22
- req = Net::HTTP::Get.new( request_uri )
23
- ## req = Net::HTTP::Get.new( "/users/geraldb" )
24
- ## req = Net::HTTP::Get.new( "/users/geraldb/repos" )
25
- req["User-Agent"] = "ruby/hubba" ## required by GitHub API
26
- req["Accept" ] = "application/vnd.github.v3+json" ## recommend by GitHub API
30
+ headers = {}
31
+ headers['User-Agent'] = 'ruby/hubba' ## required by GitHub API
32
+ headers['Accept'] = 'application/vnd.github.v3+json' ## recommend by GitHub API
27
33
 
34
+ auth = []
28
35
  ## check if credentials (user/password) present - if yes, use basic auth
29
- if @user && @password
36
+ if @token
37
+ puts " using (personal access) token - starting with: #{@token[0..6]}**********"
38
+ headers['Authorization'] = "token #{@token}"
39
+ ## token works like:
40
+ ## curl -H 'Authorization: token my_access_token' https://api.github.com/user/repos
41
+ elsif @user && @password
30
42
  puts " using basic auth - user: #{@user}, password: ***"
31
- req.basic_auth( @user, @password )
43
+ ## use credential auth "tuple" (that is, array with two string items) for now
44
+ ## or use Webclient::HttpBasicAuth or something - why? why not?
45
+ auth = [@user, @password]
46
+ # req.basic_auth( @user, @password )
47
+ else
48
+ puts " using no credentials (no token, no user/password)"
32
49
  end
33
50
 
34
- res = @http.request(req)
51
+ res = Webclient.get( url,
52
+ headers: headers,
53
+ auth: auth )
35
54
 
36
55
  # Get specific header
37
56
  # response["content-type"]
38
57
  # => "text/html; charset=UTF-8"
39
58
 
40
59
  # Iterate all response headers.
41
- res.each_header do |key, value|
42
- p "#{key} => #{value}"
60
+ res.headers.each do |key, value|
61
+ puts "#{key} => #{value}"
43
62
  end
44
63
  # => "location => http://www.google.com/"
45
64
  # => "content-type => text/html; charset=UTF-8"
46
65
  # ...
47
66
 
48
- json = JSON.parse( res.body )
49
- ## pp json
50
- json
67
+ if res.status.ok?
68
+ res.json
69
+ else
70
+ puts "!! HTTP ERROR: #{res.status.code} #{res.status.message}:"
71
+ pp res.raw
72
+ exit 1
73
+ end
51
74
  end # methdo get
52
75
 
53
76
  end ## class Client
@@ -1,13 +1,15 @@
1
- # encoding: utf-8
2
-
3
1
  module Hubba
4
2
 
5
3
  class Configuration
4
+ attr_accessor :token
5
+
6
6
  attr_accessor :user
7
7
  attr_accessor :password
8
8
 
9
9
  def initialize
10
10
  # try default setup via ENV variables
11
+ @token = ENV[ 'HUBBA_TOKEN' ]
12
+
11
13
  @user = ENV[ 'HUBBA_USER' ] ## use HUBBA_LOGIN - why? why not?
12
14
  @password = ENV[ 'HUBBA_PASSWORD' ]
13
15
  end
@@ -15,6 +17,8 @@ end
15
17
 
16
18
  ## lets you use
17
19
  ## Hubba.configure do |config|
20
+ ## config.token = 'secret'
21
+ ## #-or-
18
22
  ## config.user = 'testdada'
19
23
  ## config.password = 'secret'
20
24
  ## end
@@ -61,8 +65,16 @@ class Github
61
65
 
62
66
  def initialize( cache_dir: './cache' )
63
67
  @cache = Cache.new( cache_dir )
64
- @client = Client.new( user: Hubba.configuration.user,
65
- password: Hubba.configuration.password )
68
+
69
+ @client = if Hubba.configuration.token
70
+ Client.new( token: Hubba.configuration.token )
71
+ elsif Hubba.configuration.user &&
72
+ Hubba.configuration.password
73
+ Client.new( user: Hubba.configuration.user,
74
+ password: Hubba.configuration.password )
75
+ else
76
+ Client.new
77
+ end
66
78
 
67
79
  @offline = false
68
80
  end
@@ -104,6 +116,16 @@ def org_repos( name )
104
116
  end
105
117
 
106
118
 
119
+
120
+ def repo( full_name ) ## full_name (handle) e.g. henrythemes/jekyll-starter-theme
121
+ Resource.new( get "/repos/#{full_name}" )
122
+ end
123
+
124
+ def repo_commits( full_name )
125
+ Resource.new( get "/repos/#{full_name}/commits" )
126
+ end
127
+
128
+
107
129
  private
108
130
  def get( request_uri )
109
131
  if offline?
@@ -0,0 +1,301 @@
1
+ module Hubba
2
+
3
+ ####
4
+ # keep track of repo stats over time (with history hash)
5
+
6
+ class Stats ## todo/check: rename to GithubRepoStats or RepoStats - why? why not?
7
+
8
+ attr_reader :data
9
+
10
+ def initialize( full_name )
11
+ @data = {}
12
+ @data['full_name'] = full_name # e.g. poole/hyde etc.
13
+ end
14
+
15
+
16
+ def full_name() @full_name ||= @data['full_name']; end
17
+
18
+ ## note: return datetime objects (NOT strings); if not present/available return nil/null
19
+ def created_at() @created_at ||= @data['created_at'] ? DateTime.strptime( @data['created_at'], '%Y-%m-%dT%H:%M:%S') : nil; end
20
+ def updated_at() @updated_at ||= @data['updated_at'] ? DateTime.strptime( @data['updated_at'], '%Y-%m-%dT%H:%M:%S') : nil; end
21
+ def pushed_at() @pushed_at ||= @data['pushed_at'] ? DateTime.strptime( @data['pushed_at'], '%Y-%m-%dT%H:%M:%S') : nil; end
22
+
23
+ ## date (only) versions
24
+ def created() @created ||= @data['created_at'] ? Date.strptime( @data['created_at'], '%Y-%m-%d') : nil; end
25
+ def updated() @updated ||= @data['updated_at'] ? Date.strptime( @data['updated_at'], '%Y-%m-%d') : nil; end
26
+ def pushed() @pushed ||= @data['pushed_at'] ? Date.strptime( @data['pushed_at'], '%Y-%m-%d') : nil; end
27
+
28
+
29
+
30
+ def history() @history ||= @data['history'] ? build_history( @data['history'] ) : nil; end
31
+
32
+ def size
33
+ # size of repo in kb (as reported by github api)
34
+ @size ||= @data['size'] || 0 ## return 0 if not found - why? why not? (return nil - why? why not??)
35
+ end
36
+
37
+ def stars
38
+ ## return last stargazers_count entry (as number; 0 if not found)
39
+ @stars ||= history ? history[0].stars : 0
40
+ end
41
+
42
+
43
+ def commits() @data['commits']; end
44
+
45
+ def last_commit() ## convenience shortcut; get first/last commit (use [0]) or nil
46
+ if @data['commits'] && @data['commits'][0]
47
+ @data['commits'][0]
48
+ else
49
+ nil
50
+ end
51
+ end
52
+
53
+ def committed() ## last commit date (from author NOT committer)
54
+ @committed ||= last_commit ? Date.strptime( last_commit['author']['date'], '%Y-%m-%d') : nil
55
+ end
56
+
57
+ def committed_at() ## last commit date (from author NOT committer)
58
+ @committed_at ||= last_commit ? DateTime.strptime( last_commit['author']['date'], '%Y-%m-%dT%H:%M:%S') : nil
59
+ end
60
+
61
+
62
+ def last_commit_message() ## convenience shortcut; last commit message
63
+ h = last_commit
64
+
65
+ committer_name = h['committer']['name']
66
+ author_name = h['author']['name']
67
+ message = h['message']
68
+
69
+ buf = ""
70
+ buf << message
71
+ buf << " by #{author_name}"
72
+
73
+ if committer_name != author_name
74
+ buf << " w/ #{committer_name}"
75
+ end
76
+ end # method commit_message
77
+
78
+
79
+
80
+ def reset_cache
81
+ ## reset (invalidate) cached values from data hash
82
+ ## use after reading or fetching
83
+ @full_name = nil
84
+ @created_at = @updated_at = @pushed_at = nil
85
+ @created = @updated = @pused = nil
86
+ @history = nil
87
+ @size = nil
88
+ @stars = nil
89
+
90
+ @committed_at = nil
91
+ @committed = nil
92
+ end
93
+
94
+
95
+ ########
96
+ ## build history items (structs)
97
+
98
+ class HistoryItem
99
+
100
+ attr_reader :date, :stars ## read-only attributes
101
+ attr_accessor :prev, :next ## read/write attributes (for double linked list/nodes/items)
102
+
103
+ def initialize( date:, stars: )
104
+ @date = date
105
+ @stars = stars
106
+ @next = nil
107
+ end
108
+
109
+ ## link items (append item at the end/tail)
110
+ def append( item )
111
+ @next = item
112
+ item.prev = self
113
+ end
114
+
115
+ def diff_days
116
+ if @next
117
+ ## note: use jd=julian days for calculation
118
+ @date.jd - @next.date.jd
119
+ else
120
+ nil ## last item (tail)
121
+ end
122
+ end
123
+
124
+ def diff_stars
125
+ if @next
126
+ @stars - @next.stars
127
+ else
128
+ nil ## last item (tail)
129
+ end
130
+ end
131
+ end ## class HistoryItem
132
+
133
+
134
+ def build_history( timeseries )
135
+ items = []
136
+
137
+ keys = timeseries.keys.sort.reverse ## newest (latest) items first
138
+ keys.each do |key|
139
+ h = timeseries[ key ]
140
+
141
+ item = HistoryItem.new(
142
+ date: Date.strptime( key, '%Y-%m-%d' ),
143
+ stars: h['stargazers_count'] || 0 )
144
+
145
+ ## link items
146
+ last_item = items[-1]
147
+ last_item.append( item ) if last_item ## if not nil? append (note first item has no prev item)
148
+
149
+ items << item
150
+ end
151
+
152
+ ## todo/check: return [] for empty items array (items.empty?) - why?? why not??
153
+ if items.empty?
154
+ nil
155
+ else
156
+ items
157
+ end
158
+ end ## method build_history
159
+
160
+
161
+
162
+ def calc_diff_stars( samples: 3, days: 30 )
163
+ ## samples: use n history item samples e.g. 3 samples
164
+ ## days e.g. 7 days (per week), 30 days (per month)
165
+
166
+ if history.nil?
167
+ nil ## todo/check: return 0.0 too - why? why not?
168
+ elsif history.size == 1
169
+ ## just one item; CANNOT calc diff; return zero
170
+ 0.0
171
+ else
172
+ idx = [history.size, samples].min ## calc last index
173
+ last = history[idx-1]
174
+ first = history[0]
175
+
176
+ diff_days = first.date.jd - last.date.jd
177
+ diff_stars = first.stars - last.stars
178
+
179
+ ## note: use factor 1000 for fixed integer division
180
+ ## converts to float at the end
181
+
182
+ ## todo: check for better way (convert to float upfront - why? why not?)
183
+
184
+ diff = (diff_stars * days * 1000) / diff_days
185
+ puts "diff=#{diff}:#{diff.class.name}" ## check if it's a float
186
+ (diff.to_f/1000.0)
187
+ end
188
+ end
189
+
190
+ def history_str
191
+ ## returns "pretty printed" history as string buffer
192
+ buf = ''
193
+ buf << "[#{history.size}]: "
194
+
195
+ history.each do |item|
196
+ buf << "#{item.stars}"
197
+
198
+ diff_stars = item.diff_stars
199
+ diff_days = item.diff_days
200
+ if diff_stars && diff_days ## note: last item has no diffs
201
+ if diff_stars > 0 || diff_stars < 0
202
+ if diff_stars > 0
203
+ buf << " (+#{diff_stars}"
204
+ else
205
+ buf << " (#{diff_stars}"
206
+ end
207
+ buf << " in #{diff_days}d) "
208
+ else ## diff_stars == 0
209
+ buf << " (#{diff_days}d) "
210
+ end
211
+ end
212
+ end
213
+ buf
214
+ end # method history_str
215
+
216
+
217
+ ###############################
218
+ ## fetch / read / write methods
219
+
220
+ def fetch( gh ) ## update stats / fetch data from github via api
221
+ puts "fetching #{full_name}..."
222
+ repo = gh.repo( full_name )
223
+
224
+ ## e.g. 2015-05-11T20:21:43Z
225
+ ## puts Time.iso8601( repo.data['created_at'] )
226
+ @data['created_at'] = repo.data['created_at']
227
+ @data['updated_at'] = repo.data['updated_at']
228
+ @data['pushed_at'] = repo.data['pushed_at']
229
+
230
+ @data['size'] = repo.data['size'] # size in kb (kilobyte)
231
+
232
+ rec = {}
233
+
234
+ puts "stargazers_count"
235
+ puts repo.data['stargazers_count']
236
+ rec['stargazers_count'] = repo.data['stargazers_count']
237
+
238
+ today = Date.today.strftime( '%Y-%m-%d' ) ## e.g. 2016-09-27
239
+ puts "add record #{today} to history..."
240
+ pp rec # check if stargazers_count is a number (NOT a string)
241
+
242
+ @data[ 'history' ] ||= {}
243
+ @data[ 'history' ][ today ] = rec
244
+
245
+ ##########################
246
+ ## also check / keep track of (latest) commit
247
+ commits = gh.repo_commits( full_name )
248
+ puts "last commit/update:"
249
+ ## pp commits
250
+ commit = {
251
+ 'committer' => {
252
+ 'date' => commits.data[0]['commit']['committer']['date'],
253
+ 'name' => commits.data[0]['commit']['committer']['name']
254
+ },
255
+ 'author' => {
256
+ 'date' => commits.data[0]['commit']['author']['date'],
257
+ 'name' => commits.data[0]['commit']['author']['name']
258
+ },
259
+ 'message' => commits.data[0]['commit']['message']
260
+ }
261
+
262
+ ## for now store only the latest commit (e.g. a single commit in an array)
263
+ @data[ 'commits' ] = [commit]
264
+
265
+ pp @data
266
+
267
+ reset_cache
268
+ self ## return self for (easy chaining)
269
+ end
270
+
271
+
272
+
273
+ def write( data_dir: './data' )
274
+ basename = full_name.gsub( '/', '~' ) ## e.g. poole/hyde become poole~hyde
275
+ puts "writing stats to #{basename}..."
276
+ File.open( "#{data_dir}/#{basename}.json", 'w:utf-8' ) do |f|
277
+ f.write JSON.pretty_generate( data )
278
+ end
279
+ self ## return self for (easy chaining)
280
+ end
281
+
282
+
283
+ def read( data_dir: './data' )
284
+ ## note: skip reading if file not present
285
+ basename = full_name.gsub( '/', '~' ) ## e.g. poole/hyde become poole~hyde
286
+ filename = "#{data_dir}/#{basename}.json"
287
+ if File.exist?( filename )
288
+ puts "reading stats from #{basename}..."
289
+ json = File.open( filename, 'r:utf-8' ) { |file| file.read } ## todo/fix: use read_utf8
290
+ @data = JSON.parse( json )
291
+ reset_cache
292
+ else
293
+ puts "skipping reading stats from #{basename} -- file not found"
294
+ end
295
+ self ## return self for (easy chaining)
296
+ end
297
+
298
+ end # class Stats
299
+
300
+
301
+ end # module Hubba
@@ -1,9 +1,7 @@
1
- # encoding: utf-8
2
-
3
1
  module Hubba
4
2
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
5
- MINOR = 1
6
- PATCH = 2
3
+ MINOR = 5
4
+ PATCH = 1
7
5
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
6
 
9
7
  def self.version
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  # minitest setup
4
2
  require 'minitest/autorun'
5
3
 
@@ -0,0 +1,25 @@
1
+ {
2
+ "full_name": "jekyll/minima",
3
+ "created_at": "2016-05-20T23:07:56Z",
4
+ "updated_at": "2018-02-11T16:13:33Z",
5
+ "pushed_at": "2018-02-07T22:14:11Z",
6
+ "size": 321,
7
+ "history": {
8
+ "2018-02-12": {
9
+ "stargazers_count": 717
10
+ }
11
+ },
12
+ "commits": [
13
+ {
14
+ "author": {
15
+ "name": "ashmaroli",
16
+ "date": "2018-02-21T19:35:59Z"
17
+ },
18
+ "committer": {
19
+ "name": "Frank Taillandier",
20
+ "date": "2018-02-21T19:35:59Z"
21
+ },
22
+ "message": "social icons should resolve baseurl properly (#201)"
23
+ }
24
+ ]
25
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "full_name": "openblockchains/awesome-blockchains",
3
+ "created_at": "2017-09-13T22:33:56Z",
4
+ "size": 1620,
5
+ "history": {
6
+ "2017-12-10": {
7
+ "stargazers_count": 1084
8
+ },
9
+ "2018-01-28": {
10
+ "stargazers_count": 1411
11
+ },
12
+ "2018-02-08": {
13
+ "stargazers_count": 1526
14
+ }
15
+ },
16
+ "commits": [
17
+ {
18
+ "committer": {
19
+ "date": "2018-02-08T09:33:28Z",
20
+ "name": "Gerald Bauer"
21
+ },
22
+ "message": "Update README.md\n\nJust a little typo cryto -> crypto."
23
+ }
24
+ ],
25
+ "updated_at": "2018-02-08T19:26:35Z",
26
+ "pushed_at": "2018-02-08T09:33:29Z"
27
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "full_name": "opendatajson/factbook.json",
3
+ "created_at": "2014-07-12T12:43:52Z",
4
+ "history": {
5
+ "2017-02-11": {
6
+ "stargazers_count": 457
7
+ },
8
+ "2017-02-12": {
9
+ "stargazers_count": 457
10
+ },
11
+ "2017-06-18": {
12
+ "stargazers_count": 505
13
+ },
14
+ "2017-07-28": {
15
+ "stargazers_count": 512
16
+ },
17
+ "2017-12-10": {
18
+ "stargazers_count": 533
19
+ },
20
+ "2018-01-28": {
21
+ "stargazers_count": 536
22
+ },
23
+ "2018-02-08": {
24
+ "stargazers_count": 539
25
+ }
26
+ },
27
+ "commits": [
28
+ {
29
+ "committer": {
30
+ "date": "2017-03-29T17:23:29Z",
31
+ "name": "GitHub"
32
+ },
33
+ "message": "Update MONGO.md"
34
+ }
35
+ ],
36
+ "size": 7355,
37
+ "updated_at": "2018-02-01T12:35:19Z",
38
+ "pushed_at": "2017-03-29T17:23:30Z"
39
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "full_name": "poole/hyde",
3
+ "created_at": "2013-02-07T07:01:38Z",
4
+ "updated_at": "2018-02-12T05:44:07Z",
5
+ "pushed_at": "2018-01-14T02:41:16Z",
6
+ "size": 28428,
7
+ "history": {
8
+ "2018-02-12": {
9
+ "stargazers_count": 2125
10
+ }
11
+ },
12
+ "commits": [
13
+ {
14
+ "committer": {
15
+ "date": "2015-05-11T20:21:43Z",
16
+ "name": "Mark Otto"
17
+ },
18
+ "message": "Merge pull request #91 from pborreli/patch-1\n\nFixed typo"
19
+ }
20
+ ]
21
+ }
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  ###
4
2
  # to run use
5
3
  # ruby -I ./lib -I ./test test/test_cache.rb
@@ -32,15 +30,14 @@ class TestCache < MiniTest::Test
32
30
  def test_cache
33
31
  orgs = @cache.get( '/users/geraldb/orgs' )
34
32
  assert_equal 4, orgs.size
35
-
33
+
36
34
  repos = @cache.get( '/users/geraldb/repos' )
37
35
  assert_equal 3, repos.size
38
36
  end # method test_cache
39
37
 
40
38
  def test_cache_miss
41
- assert_equal nil, @cache.get( '/test/hello' )
42
- assert_equal nil, @cache.get( '/test/hola' )
39
+ assert_nil @cache.get( '/test/hello' )
40
+ assert_nil @cache.get( '/test/hola' )
43
41
  end # method test_cache_miss
44
42
 
45
43
  end # class TestCache
46
-
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  ###
4
2
  # to run use
5
3
  # ruby -I ./lib -I ./test test/test_config.rb
@@ -0,0 +1,122 @@
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_stats.rb
4
+
5
+
6
+ require 'helper'
7
+
8
+
9
+ class TestStats < MiniTest::Test
10
+
11
+
12
+ def test_jekyll_minima
13
+
14
+ stats = Hubba::Stats.new( 'jekyll/minima' )
15
+
16
+ assert_equal 0, stats.size
17
+ assert_equal 0, stats.stars
18
+ assert_nil stats.history
19
+
20
+ stats.read( data_dir: "#{Hubba.root}/test/stats" )
21
+
22
+ assert_equal 321, stats.size
23
+ assert_equal 717, stats.stars
24
+ assert_equal 717, stats.history[0].stars
25
+ assert_equal 1, stats.history.size
26
+
27
+ assert_equal Date.new(2018, 2, 12 ), stats.history[0].date
28
+
29
+ assert_nil stats.history[0].diff_days
30
+
31
+ assert_equal Date.new(2018, 2, 21 ), stats.committed
32
+ assert_equal Date.new(2016, 5, 20 ), stats.created
33
+ assert_equal Date.new(2018, 2, 11 ), stats.updated
34
+ assert_equal Date.new(2018, 2, 7 ), stats.pushed
35
+
36
+ assert_equal DateTime.new(2018, 2, 21, 19, 35, 59 ), stats.committed_at
37
+ assert_equal DateTime.new(2016, 5, 20, 23, 7, 56 ), stats.created_at
38
+ assert_equal DateTime.new(2018, 2, 11, 16, 13, 33 ), stats.updated_at
39
+ assert_equal DateTime.new(2018, 2, 7, 22, 14, 11 ), stats.pushed_at
40
+
41
+
42
+ pp stats.last_commit
43
+ pp stats.last_commit_message
44
+ pp stats.history_str ## pp history pretty printed to string (buffer)
45
+ end
46
+
47
+
48
+
49
+ def test_awesome_blockchains
50
+
51
+ stats = Hubba::Stats.new( 'openblockchains/awesome-blockchains' )
52
+
53
+ assert_equal 0, stats.size
54
+ assert_equal 0, stats.stars
55
+ assert_nil stats.history
56
+
57
+ stats.read( data_dir: "#{Hubba.root}/test/stats" )
58
+
59
+ assert_equal 1620, stats.size
60
+ assert_equal 1526, stats.stars
61
+ assert_equal 1526, stats.history[0].stars
62
+ assert_equal 1411, stats.history[1].stars
63
+ assert_equal 1084, stats.history[2].stars
64
+ assert_equal 1084, stats.history[-1].stars
65
+ assert_equal 3, stats.history.size
66
+
67
+ assert_equal Date.new(2018, 2, 8 ), stats.history[0].date
68
+ assert_equal Date.new(2018, 1, 28 ), stats.history[1].date
69
+ assert_equal Date.new(2017, 12, 10 ), stats.history[2].date
70
+
71
+ assert_equal 11, stats.history[0].diff_days
72
+ assert_equal 49, stats.history[1].diff_days
73
+ assert_nil stats.history[2].diff_days
74
+
75
+ assert_equal 115, stats.history[0].diff_stars
76
+ assert_equal 327, stats.history[1].diff_stars
77
+ assert_nil stats.history[2].diff_stars
78
+
79
+ assert_equal 221.0, stats.calc_diff_stars ## defaults to samples: 3, days: 30
80
+ assert_equal 51.566, stats.calc_diff_stars( samples: 5, days: 7 )
81
+
82
+ pp stats.history_str ## pp history pretty printed to string (buffer)
83
+ end
84
+
85
+
86
+ def test_factbook_json
87
+
88
+ stats = Hubba::Stats.new( 'opendatajson/factbook.json' )
89
+
90
+ assert_equal 0, stats.size
91
+ assert_equal 0, stats.stars
92
+ assert_nil stats.history
93
+
94
+ stats.read( data_dir: "#{Hubba.root}/test/stats" )
95
+
96
+ assert_equal 7355, stats.size
97
+ assert_equal 539, stats.stars
98
+ assert_equal 539, stats.history[0].stars
99
+ assert_equal 536, stats.history[1].stars
100
+ assert_equal 533, stats.history[2].stars
101
+ assert_equal 457, stats.history[-1].stars
102
+ assert_equal 7, stats.history.size
103
+
104
+ assert_equal Date.new(2018, 2, 8 ), stats.history[0].date
105
+ assert_equal Date.new(2018, 1, 28 ), stats.history[1].date
106
+ assert_equal Date.new(2017, 12, 10 ), stats.history[2].date
107
+
108
+ assert_equal 11, stats.history[0].diff_days
109
+ assert_equal 49, stats.history[1].diff_days
110
+ assert_nil stats.history[-1].diff_days
111
+
112
+ assert_equal 3, stats.history[0].diff_stars
113
+ assert_equal 3, stats.history[1].diff_stars
114
+ assert_nil stats.history[-1].diff_stars
115
+
116
+ assert_equal 3.0, stats.calc_diff_stars ## defaults to samples: 3, days: 30
117
+ assert_equal 1.012, stats.calc_diff_stars( samples: 5, days: 7 )
118
+
119
+ pp stats.history_str ## pp history pretty printed to string (buffer)
120
+ end
121
+
122
+ end # class TestStats
@@ -0,0 +1,41 @@
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_stats_tmp.rb
4
+
5
+
6
+ require 'helper'
7
+
8
+
9
+ class TestStatsTmp < MiniTest::Test
10
+
11
+ def setup
12
+ @gh = Hubba::Github.new( cache_dir: "#{Hubba.root}/test/cache" )
13
+ end
14
+
15
+ def test_stats
16
+ repos = [
17
+ 'poole/hyde',
18
+ 'jekyll/minima'
19
+ ]
20
+
21
+ repos.each do |repo|
22
+ stats = Hubba::Stats.new( repo )
23
+ # stats.read( data_dir: './tmp' )
24
+ stats.read( data_dir: "#{Hubba.root}/test/stats" )
25
+
26
+ puts "stars before fetch: #{stats.stars}"
27
+ puts "size before fetch: #{stats.size} kb"
28
+
29
+ ## note/todo: enable for "live" online testing
30
+ ## stats.fetch( @gh )
31
+
32
+ puts "stars after fetch: #{stats.stars}"
33
+ puts "size after fetch: #{stats.size} kb"
34
+
35
+ stats.write( data_dir: './tmp' )
36
+ end
37
+
38
+ assert true # for now everything ok if we get here
39
+ end
40
+
41
+ end # class TestStatsTmp
metadata CHANGED
@@ -1,67 +1,73 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hubba
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-17 00:00:00.000000000 Z
11
+ date: 2020-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: logutils
14
+ name: webclient
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 0.1.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 0.1.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rdoc
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '4.0'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '7'
34
37
  type: :development
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - "~>"
41
+ - - ">="
39
42
  - !ruby/object:Gem::Version
40
43
  version: '4.0'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '7'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: hoe
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: '3.14'
53
+ version: '3.22'
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
58
  - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: '3.14'
55
- description: hubba - (yet) another (lite) GitHub HTTP API client / library
60
+ version: '3.22'
61
+ description: hubba - (yet) another (lite) GitHub HTTP API client / library
56
62
  email: ruby-talk@ruby-lang.org
57
63
  executables: []
58
64
  extensions: []
59
65
  extra_rdoc_files:
60
- - HISTORY.md
66
+ - CHANGELOG.md
61
67
  - Manifest.txt
62
68
  - README.md
63
69
  files:
64
- - HISTORY.md
70
+ - CHANGELOG.md
65
71
  - Manifest.txt
66
72
  - README.md
67
73
  - Rakefile
@@ -69,13 +75,20 @@ files:
69
75
  - lib/hubba/cache.rb
70
76
  - lib/hubba/client.rb
71
77
  - lib/hubba/github.rb
78
+ - lib/hubba/stats.rb
72
79
  - lib/hubba/version.rb
73
80
  - test/cache/users~geraldb~orgs.json
74
81
  - test/cache/users~geraldb~repos.json
75
82
  - test/helper.rb
83
+ - test/stats/jekyll~minima.json
84
+ - test/stats/openblockchains~awesome-blockchains.json
85
+ - test/stats/opendatajson~factbook.json.json
86
+ - test/stats/poole~hyde.json
76
87
  - test/test_cache.rb
77
88
  - test/test_config.rb
78
- homepage: https://github.com/rubylibs/hubba
89
+ - test/test_stats.rb
90
+ - test/test_stats_tmp.rb
91
+ homepage: https://github.com/rubycoco/git
79
92
  licenses:
80
93
  - Public Domain
81
94
  metadata: {}
@@ -89,7 +102,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
89
102
  requirements:
90
103
  - - ">="
91
104
  - !ruby/object:Gem::Version
92
- version: 1.9.2
105
+ version: 2.2.2
93
106
  required_rubygems_version: !ruby/object:Gem::Requirement
94
107
  requirements:
95
108
  - - ">="
@@ -97,8 +110,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
110
  version: '0'
98
111
  requirements: []
99
112
  rubyforge_project:
100
- rubygems_version: 2.2.3
113
+ rubygems_version: 2.5.2
101
114
  signing_key:
102
115
  specification_version: 4
103
- summary: hubba - (yet) another (lite) GitHub HTTP API client / library
116
+ summary: hubba - (yet) another (lite) GitHub HTTP API client / library
104
117
  test_files: []