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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e3e04406b046b751a5eb400e8955417ae99498e7
4
- data.tar.gz: 57752bfd47aea766d3db5c467659876216a644a0
3
+ metadata.gz: 122527cdc3cddb68e2c54a6e51fcfb77c2c91c0c
4
+ data.tar.gz: 6bb52baff0536f55ad969885fc8500b031457e44
5
5
  SHA512:
6
- metadata.gz: f96d7fa167b0e7cf8b685674aa80d19eca790ad237a9ea43cd40650d1c799448ce5827b009bb84b9d14c774b991693e1b0570735bf6573f64ed2c0a9e46c1c1f
7
- data.tar.gz: 5cbdcd4a949763f19ba6275cec64cc1f3cfda6b05abe02950721befac8df17b1a5a1d64d1e41ae8048d23c06b93f41436d69bde91338e81313aa6e19af89236a
6
+ metadata.gz: df4e036a205be30371ec9de85e8085717235922fcc21e22f9f516cc40481a2a8cf6a9b0edd0a37cb24759059a08b5ea74957f41f89139bf9e1a860ed20029e3b
7
+ data.tar.gz: 698fc0d240aa6c6f8b125d1ae004beacf5ae97c220eb42d4fd542a49a656ece101e3a9fd9e740eaefb63e7f03c132458872f4ea5949cd30e2eceb9ccc3bb9e54
File without changes
@@ -1,21 +1,20 @@
1
- HISTORY.md
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/gittiscripts/hubba](https://github.com/gittiscripts/hubba)
6
- * bugs :: [github.com/gittiscripts/hubba/issues](https://github.com/gittiscripts/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
-
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 = ['https://github.com/gittiscripts/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: '>= 2.3'
27
+ required_ruby_version: '>= 2.2.2'
28
28
  }
29
29
 
30
30
  end
@@ -1,25 +1,43 @@
1
- # encoding: utf-8
1
+ # 3rd party (our own)
2
+ require 'webclient'
2
3
 
3
- require 'net/http'
4
- require "net/https"
5
- require 'uri'
6
4
 
7
- require 'pp'
8
- require 'json'
9
- require 'yaml'
10
- require 'time'
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/cache'
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?($RUBYLIBS_DEBUG)
43
+ puts Hubba.banner if defined?($RUBYCOCO_DEBUG)
@@ -1,53 +1,79 @@
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 )
20
23
  puts "GET #{request_uri}"
21
24
 
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
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 @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}"
43
- end
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
- json = JSON.parse( res.body )
49
- ## pp json
50
- json
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
@@ -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
@@ -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( cache_dir: './cache' )
63
- @cache = Cache.new( cache_dir )
64
- @client = Client.new( user: Hubba.configuration.user,
65
- password: Hubba.configuration.password )
66
-
67
- @offline = false
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
- private
118
- def get( request_uri )
119
- if offline?
120
- @cache.get( request_uri )
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
- @client.get( request_uri )
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
- end # module Hubba
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