hubba 0.4.0 → 0.6.1
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.
- checksums.yaml +4 -4
- data/{HISTORY.md → CHANGELOG.md} +0 -0
- data/Manifest.txt +4 -5
- data/README.md +20 -20
- data/Rakefile +4 -4
- data/lib/hubba.rb +30 -12
- data/lib/hubba/client.rb +47 -21
- data/lib/hubba/config.rb +51 -0
- data/lib/hubba/github.rb +60 -51
- data/lib/hubba/reports.rb +249 -0
- data/lib/hubba/reposet.rb +170 -0
- data/lib/hubba/stats.rb +104 -33
- data/lib/hubba/version.rb +2 -4
- data/test/helper.rb +0 -2
- data/test/stats/jekyll~minima.json +8 -4
- data/test/test_config.rb +10 -2
- data/test/test_stats.rb +44 -5
- data/test/test_stats_tmp.rb +8 -7
- metadata +22 -17
- data/lib/hubba/cache.rb +0 -62
- data/test/cache/users~geraldb~orgs.json +0 -46
- data/test/cache/users~geraldb~repos.json +0 -263
- data/test/test_cache.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 122527cdc3cddb68e2c54a6e51fcfb77c2c91c0c
|
4
|
+
data.tar.gz: 6bb52baff0536f55ad969885fc8500b031457e44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df4e036a205be30371ec9de85e8085717235922fcc21e22f9f516cc40481a2a8cf6a9b0edd0a37cb24759059a08b5ea74957f41f89139bf9e1a860ed20029e3b
|
7
|
+
data.tar.gz: 698fc0d240aa6c6f8b125d1ae004beacf5ae97c220eb42d4fd542a49a656ece101e3a9fd9e740eaefb63e7f03c132458872f4ea5949cd30e2eceb9ccc3bb9e54
|
data/{HISTORY.md → CHANGELOG.md}
RENAMED
File without changes
|
data/Manifest.txt
CHANGED
@@ -1,21 +1,20 @@
|
|
1
|
-
|
1
|
+
CHANGELOG.md
|
2
2
|
Manifest.txt
|
3
3
|
README.md
|
4
4
|
Rakefile
|
5
5
|
lib/hubba.rb
|
6
|
-
lib/hubba/cache.rb
|
7
6
|
lib/hubba/client.rb
|
7
|
+
lib/hubba/config.rb
|
8
8
|
lib/hubba/github.rb
|
9
|
+
lib/hubba/reports.rb
|
10
|
+
lib/hubba/reposet.rb
|
9
11
|
lib/hubba/stats.rb
|
10
12
|
lib/hubba/version.rb
|
11
|
-
test/cache/users~geraldb~orgs.json
|
12
|
-
test/cache/users~geraldb~repos.json
|
13
13
|
test/helper.rb
|
14
14
|
test/stats/jekyll~minima.json
|
15
15
|
test/stats/openblockchains~awesome-blockchains.json
|
16
16
|
test/stats/opendatajson~factbook.json.json
|
17
17
|
test/stats/poole~hyde.json
|
18
|
-
test/test_cache.rb
|
19
18
|
test/test_config.rb
|
20
19
|
test/test_stats.rb
|
21
20
|
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/
|
6
|
-
* bugs :: [github.com/
|
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.
|
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
@@ -8,23 +8,23 @@ Hoe.spec 'hubba' do
|
|
8
8
|
self.summary = 'hubba - (yet) another (lite) GitHub HTTP API client / library'
|
9
9
|
self.description = summary
|
10
10
|
|
11
|
-
self.urls =
|
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 = '
|
18
|
+
self.history_file = 'CHANGELOG.md'
|
19
19
|
|
20
20
|
self.extra_deps = [
|
21
|
-
['
|
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: '>= 2.
|
27
|
+
required_ruby_version: '>= 2.2.2'
|
28
28
|
}
|
29
29
|
|
30
30
|
end
|
data/lib/hubba.rb
CHANGED
@@ -1,25 +1,43 @@
|
|
1
|
-
#
|
1
|
+
# 3rd party (our own)
|
2
|
+
require 'webclient'
|
2
3
|
|
3
|
-
require 'net/http'
|
4
|
-
require "net/https"
|
5
|
-
require 'uri'
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
###############
|
6
|
+
## helpers
|
7
|
+
|
8
|
+
def save_json( path, data ) ## data - hash or array
|
9
|
+
File.open( path, 'w:utf-8' ) do |f|
|
10
|
+
f.write( JSON.pretty_generate( data ))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def save_yaml( path, data )
|
15
|
+
File.open( path, 'w:utf-8' ) do |f|
|
16
|
+
f.write( data.to_yaml )
|
17
|
+
end
|
18
|
+
end
|
11
19
|
|
12
20
|
|
13
|
-
# 3rd party gems/libs
|
14
|
-
require 'logutils'
|
15
21
|
|
16
22
|
# our own code
|
17
23
|
require 'hubba/version' # note: let version always go first
|
18
|
-
require 'hubba/
|
24
|
+
require 'hubba/config'
|
19
25
|
require 'hubba/client'
|
20
26
|
require 'hubba/github'
|
21
27
|
require 'hubba/stats'
|
22
28
|
|
29
|
+
## "higher level" porcelain services / helpers for easy (re)use
|
30
|
+
require 'hubba/reposet'
|
31
|
+
|
32
|
+
require 'hubba/reports'
|
33
|
+
|
34
|
+
|
35
|
+
############
|
36
|
+
# add convenience alias for alternate spelling - why? why not?
|
37
|
+
module Hubba
|
38
|
+
GitHub = Github
|
39
|
+
end
|
40
|
+
|
23
41
|
|
24
42
|
# say hello
|
25
|
-
puts Hubba.banner if defined?($
|
43
|
+
puts Hubba.banner if defined?($RUBYCOCO_DEBUG)
|
data/lib/hubba/client.rb
CHANGED
@@ -1,53 +1,79 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Hubba
|
4
2
|
|
5
3
|
|
6
4
|
class Client
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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 )
|
20
23
|
puts "GET #{request_uri}"
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
req["Accept" ] = "application/vnd.github.v3+json" ## recommend by GitHub API
|
25
|
+
## note: request_uri ALWAYS starts with leading /, thus use + for now!!!
|
26
|
+
# e.g. /users/geraldb
|
27
|
+
# /users/geraldb/repos
|
28
|
+
url = BASE_URL + request_uri
|
27
29
|
|
30
|
+
headers = {}
|
31
|
+
headers['User-Agent'] = 'ruby/hubba' ## required by GitHub API
|
32
|
+
headers['Accept'] = 'application/vnd.github.v3+json' ## recommend by GitHub API
|
33
|
+
|
34
|
+
auth = []
|
28
35
|
## check if credentials (user/password) present - if yes, use basic auth
|
29
|
-
if @
|
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
|
-
|
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 =
|
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
|
-
|
42
|
-
|
43
|
-
|
60
|
+
# puts "HTTP HEADERS:"
|
61
|
+
# res.headers.each do |key, value|
|
62
|
+
# puts " #{key}: >#{value}<"
|
63
|
+
# end
|
64
|
+
# puts
|
65
|
+
|
44
66
|
# => "location => http://www.google.com/"
|
45
67
|
# => "content-type => text/html; charset=UTF-8"
|
46
68
|
# ...
|
47
69
|
|
48
|
-
|
49
|
-
|
50
|
-
|
70
|
+
if res.status.ok?
|
71
|
+
res.json
|
72
|
+
else
|
73
|
+
puts "!! HTTP ERROR: #{res.status.code} #{res.status.message}:"
|
74
|
+
pp res.raw
|
75
|
+
exit 1
|
76
|
+
end
|
51
77
|
end # methdo get
|
52
78
|
|
53
79
|
end ## class Client
|
data/lib/hubba/config.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Hubba
|
2
|
+
|
3
|
+
class Configuration
|
4
|
+
def data_dir() @data_dir || './data'; end
|
5
|
+
def data_dir=( value ) @data_dir = value; end
|
6
|
+
|
7
|
+
### todo/check: rename to/use tmp_dir - why? why not?
|
8
|
+
def cache_dir() @cache_dir || './cache'; end
|
9
|
+
def cache_dir=( value ) @cache_dir = value; end
|
10
|
+
|
11
|
+
|
12
|
+
# try default setup via ENV variables
|
13
|
+
def token() @token || ENV[ 'HUBBA_TOKEN' ]; end
|
14
|
+
def token=( value ) @token = value; end
|
15
|
+
|
16
|
+
# todo/check: use HUBBA_LOGIN - why? why not?
|
17
|
+
def user() @user || ENV[ 'HUBBA_USER' ]; end
|
18
|
+
def password() @password || ENV[ 'HUBBA_PASSWORD' ]; end
|
19
|
+
def user=( value ) @user = value; end
|
20
|
+
def password=( value ) @password = value; end
|
21
|
+
|
22
|
+
end # class Configuration
|
23
|
+
|
24
|
+
|
25
|
+
## lets you use
|
26
|
+
## Hubba.configure do |config|
|
27
|
+
## config.token = 'secret'
|
28
|
+
## -or-
|
29
|
+
## config.user = 'testdada'
|
30
|
+
## config.password = 'secret'
|
31
|
+
## end
|
32
|
+
##
|
33
|
+
## move configure block to GitHub class - why? why not?
|
34
|
+
## e.g. GitHub.configure do |config|
|
35
|
+
## ...
|
36
|
+
## end
|
37
|
+
|
38
|
+
|
39
|
+
def self.configuration
|
40
|
+
@configuration ||= Configuration.new
|
41
|
+
end
|
42
|
+
class << self
|
43
|
+
alias_method :config, :configuration
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def self.configure
|
48
|
+
yield( configuration )
|
49
|
+
end
|
50
|
+
|
51
|
+
end # module Hubba
|
data/lib/hubba/github.rb
CHANGED
@@ -1,38 +1,5 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module Hubba
|
4
2
|
|
5
|
-
class Configuration
|
6
|
-
attr_accessor :user
|
7
|
-
attr_accessor :password
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
# try default setup via ENV variables
|
11
|
-
@user = ENV[ 'HUBBA_USER' ] ## use HUBBA_LOGIN - why? why not?
|
12
|
-
@password = ENV[ 'HUBBA_PASSWORD' ]
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
## lets you use
|
17
|
-
## Hubba.configure do |config|
|
18
|
-
## config.user = 'testdada'
|
19
|
-
## config.password = 'secret'
|
20
|
-
## end
|
21
|
-
##
|
22
|
-
## move configure block to GitHub class - why? why not?
|
23
|
-
## e.g. GitHub.configure do |config|
|
24
|
-
## ...
|
25
|
-
## end
|
26
|
-
|
27
|
-
|
28
|
-
def self.configuration
|
29
|
-
@configuration ||= Configuration.new
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.configure
|
33
|
-
yield( configuration )
|
34
|
-
end
|
35
|
-
|
36
3
|
|
37
4
|
class Resource
|
38
5
|
attr_reader :data
|
@@ -53,25 +20,25 @@ class Orgs < Resource
|
|
53
20
|
## sort by name
|
54
21
|
data.map { |item| item['login'] }.sort
|
55
22
|
end
|
23
|
+
alias_method :names, :logins ## add name alias - why? why not?
|
56
24
|
end
|
57
25
|
|
58
26
|
|
59
27
|
|
60
28
|
class Github
|
61
29
|
|
62
|
-
def initialize
|
63
|
-
@
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
30
|
+
def initialize
|
31
|
+
@client = if Hubba.configuration.token
|
32
|
+
Client.new( token: Hubba.configuration.token )
|
33
|
+
elsif Hubba.configuration.user &&
|
34
|
+
Hubba.configuration.password
|
35
|
+
Client.new( user: Hubba.configuration.user,
|
36
|
+
password: Hubba.configuration.password )
|
37
|
+
else
|
38
|
+
Client.new
|
39
|
+
end
|
68
40
|
end
|
69
41
|
|
70
|
-
def offline!() @offline = true; end ## switch to offline - todo: find a "better" way - why? why not?
|
71
|
-
def online!() @offline = false; end
|
72
|
-
def offline?() @offline == true; end
|
73
|
-
def online?() @offline == false; end
|
74
|
-
|
75
42
|
|
76
43
|
def user( name )
|
77
44
|
Resource.new( get "/users/#{name}" )
|
@@ -95,6 +62,7 @@ def user_orgs( name )
|
|
95
62
|
end
|
96
63
|
|
97
64
|
|
65
|
+
|
98
66
|
def org( name )
|
99
67
|
Resource.new( get "/orgs/#{name}" )
|
100
68
|
end
|
@@ -114,15 +82,56 @@ def repo_commits( full_name )
|
|
114
82
|
end
|
115
83
|
|
116
84
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
85
|
+
|
86
|
+
####
|
87
|
+
# more
|
88
|
+
def update( obj )
|
89
|
+
if obj.is_a?( Stats )
|
90
|
+
stats = obj
|
91
|
+
full_name = stats.full_name
|
92
|
+
puts "[update 1/2] fetching repo >#{full_name}<..."
|
93
|
+
repo = repo( full_name )
|
94
|
+
puts "[update 2/2] fetching repo >#{full_name}< commits ..."
|
95
|
+
commits = repo_commits( full_name )
|
96
|
+
|
97
|
+
stats.update( repo, commits )
|
121
98
|
else
|
122
|
-
|
99
|
+
raise ArgumentError, "unknown source object passed in - expected Hubba::Stats; got #{obj.class.name}"
|
123
100
|
end
|
124
101
|
end
|
125
102
|
|
126
|
-
end # class Github
|
127
103
|
|
128
|
-
|
104
|
+
def update_stats( h ) ## todo/fix: change to Reposet - why? why not???
|
105
|
+
h.each do |org_with_counter,names|
|
106
|
+
|
107
|
+
## remove optional number from key e.g.
|
108
|
+
## mrhydescripts (3) => mrhydescripts
|
109
|
+
## footballjs (4) => footballjs
|
110
|
+
## etc.
|
111
|
+
|
112
|
+
org = org_with_counter.sub( /\([0-9]+\)/, '' ).strip
|
113
|
+
|
114
|
+
## puts " -- #{key_with_counter} [#{key}] --"
|
115
|
+
|
116
|
+
names.each do |name|
|
117
|
+
full_name = "#{org}/#{name}"
|
118
|
+
|
119
|
+
## puts " fetching stats #{count+1}/#{repo_count} - >#{full_name}<..."
|
120
|
+
stats = Stats.new( full_name )
|
121
|
+
stats.read
|
122
|
+
|
123
|
+
update( stats ) ## fetch & update stats
|
124
|
+
|
125
|
+
stats.write
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
private
|
132
|
+
def get( request_uri )
|
133
|
+
@client.get( request_uri )
|
134
|
+
end
|
135
|
+
|
136
|
+
end # class Github
|
137
|
+
end # module Hubba
|