hubba 0.6.2 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0c7c4d9d7af183756855559bc03b8910bdcb1ace
4
- data.tar.gz: 4cfd725ee9c1a3138370cbcb61e1bd900d689012
3
+ metadata.gz: 6dfdf158420e74f4a2810c18e46cab065aa2dcce
4
+ data.tar.gz: 51357a2974422d2e9c4c0bb7b961d08ee43297bd
5
5
  SHA512:
6
- metadata.gz: a6cb53226a5a73777bc9ad86d82a22a39ea56710514233d5530b489d9fcce1bd9cc67b65f6d41f488d3ee4a266e0be5cbcbeef9231cef9007427928d60785214
7
- data.tar.gz: 38395c69b0e45a174a1629029803f41b3e5d1ca7dba27d893dfcebd70f59ed4f17e60e6ec1715c331b61d8e49ef727de564aba14a03b0dfe75a6c15850e3bdc8
6
+ metadata.gz: 7388e0646b07392b35ad13ea738c440b49f37cca283b4abf380071069ce48ef22bbe2d9fe293e266056ee1c7c386c92547740bb84a74cf3c03651a1f48ac48b2
7
+ data.tar.gz: 4ffbc0a84814db71694e6f0d750c7269916ae30f46a64ca79679976de222e06cbb63918b73b47c679ef8b92fa4fc9abce86f2cc3128903c1e2c8da634cfd96e2
@@ -4,19 +4,11 @@ README.md
4
4
  Rakefile
5
5
  lib/hubba.rb
6
6
  lib/hubba/config.rb
7
- lib/hubba/folio.rb
8
7
  lib/hubba/github.rb
9
- lib/hubba/hubba.rb
10
- lib/hubba/reports.rb
8
+ lib/hubba/reposet.rb
11
9
  lib/hubba/stats.rb
12
10
  lib/hubba/update.rb
13
11
  lib/hubba/update_traffic.rb
14
12
  lib/hubba/version.rb
15
13
  test/helper.rb
16
- test/stats/jekyll~minima.json
17
- test/stats/openblockchains~awesome-blockchains.json
18
- test/stats/opendatajson~factbook.json.json
19
- test/stats/poole~hyde.json
20
14
  test/test_config.rb
21
- test/test_stats.rb
22
- test/test_stats_tmp.rb
data/README.md CHANGED
@@ -87,6 +87,8 @@ account that are forks get auto-excluded.
87
87
  ### Step 2: Update repo statistics (daily / weekly / monthly)
88
88
 
89
89
 
90
+ #### Basics (commits, stars, forks, topics, etc.)
91
+
90
92
  Use `update_stats` to
91
93
  to get the latest commit, star count and more for all your repos
92
94
  listed in `./repos.yml` via the GitHub API:
@@ -99,150 +101,27 @@ Note: By default the datafiles (one per repo)
99
101
  get stored in the `./data` directory.
100
102
 
101
103
 
104
+ #### Traffic (page views, clones, referrers, etc.)
102
105
 
103
-
104
- ### Step 3: Generate some statistics / reports
105
-
106
-
107
- Hubba has four built-in reports (for now):
108
-
109
- - `ReportSummary` - A-Z list of your repos by orgs with stars and size in kb
110
- - `ReportStars` - your repos ranked by stars
111
- - `ReportTimeline` - your repos in reverse chronological order by creation
112
- - `ReportUpdates` - your repos in reverse chronological order by last commit
113
-
114
-
115
- If you only generate a single report, use:
116
-
117
- ``` ruby
118
- report = Hubba::ReportSummary.new( './repos.yml' )
119
- report.save( './SUMMARY.md' )
120
- ```
121
-
122
-
123
- If you generate more reports, (re)use the in-memory statistics cache / object:
106
+ Use `update_traffic` to
107
+ to get the latest traffic stats (page views, clones, referrers, etc.)
108
+ for all your repos listed in `./repos.yml` via the GitHub API.
124
109
 
125
110
  ``` ruby
126
- stats = Hubba.stats( './repos.yml' )
127
-
128
- report = Hubba::ReportSummary.new( stats )
129
- report.save( './SUMMARY.md' )
130
-
131
- report = Hubba::ReportStars.new( stats )
132
- report.save( './STARS.md' )
133
-
134
- report = Hubba::ReportTimeline.new( stats )
135
- report.save( './TIMELINE.md' )
136
-
137
- report = Hubba::ReportUpdates.new( stats )
138
- report.save( './UPDATES.md' )
111
+ Hubba.update_traffic( './repos.yml' )
139
112
  ```
140
113
 
114
+ Note: Access to traffic statistics via the GitHub API
115
+ requires push access for your GitHub (personal access) token.
141
116
 
142
- ### Report Examples
143
-
144
- #### Report Example - Summary
145
-
146
- A-Z list of your repos by orgs with stars and size in kb.
147
- Results in:
148
-
149
- ---
150
-
151
- > 593 repos @ 83 orgs
152
- >
153
- > ### geraldb _(11)_
154
- >
155
- > **austria** ★1 (552 kb) · **catalog** ★3 (156 kb) · **chelitas** ★1 (168 kb) · **geraldb.github.io** ★1 (520 kb) · **logos** ★1 (363 kb) · **sandbox** ★2 (529 kb) · **talks** ★200 (16203 kb) · **web-proxy-win** ★8 (152 kb) · **webcomponents** ★1 (164 kb) · **webpub-reader** ★3 (11 kb) · **wine.db.tools** ★1 (252 kb)
156
- >
157
- > ...
158
-
159
- ---
160
-
161
- (Live Example - [`SUMMARY.md`](https://github.com/yorobot/backup/blob/master/SUMMARY.md))
162
-
163
-
164
- #### Report Example - Stars
165
-
166
- Your repos ranked by stars. Results in:
167
-
168
- ---
169
-
170
- > 593 repos @ 83 orgs
171
- >
172
- > 1. ★2936 **openblockchains/awesome-blockchains** (2514 kb)
173
- > 2. ★851 **planetjekyll/awesome-jekyll-plugins** (148 kb)
174
- > 3. ★604 **factbook/factbook.json** (7355 kb)
175
- > 4. ★593 **openfootball/football.json** (2135 kb)
176
- > 5. ★570 **openmundi/world.db** (1088 kb)
177
- > 6. ★552 **openblockchains/programming-blockchains** (552 kb)
178
- > 7. ★547 **mundimark/awesome-markdown** (83 kb)
179
- > 8. ★532 **planetjekyll/awesome-jekyll** (110 kb)
180
- > 9. ★489 **cryptocopycats/awesome-cryptokitties** (4154 kb)
181
- > 10. ★445 **openfootball/world-cup** (638 kb)
182
- >
183
- > ...
184
-
185
- ---
186
-
187
- (Live Example: [`STARS.md`](https://github.com/yorobot/backup/blob/master/STARS.md))
188
-
189
-
190
- #### Report Example - Timeline
191
-
192
- Your repos in reverse chronological order by creation.
193
- Results in:
194
-
195
- ---
196
-
197
- > 593 repos @ 83 orgs
198
- >
199
- > ## 2020
200
- >
201
- > ### 9
202
- >
203
- > - 2020-09-18 ★1 **yorobot/workflow** (83 kb)
204
- >
205
- > ### 6
206
- >
207
- > - 2020-06-27 ★2 **yorobot/sport.db.more** (80 kb)
208
- > - 2020-06-24 ★1 **yorobot/stage** (554 kb)
209
- > - 2020-06-11 ★1 **yorobot/cache.csv** (336 kb)
210
- >
211
- > ...
212
-
213
- ---
214
-
215
- (Live Example: [`TIMELINE.md`](https://github.com/yorobot/backup/blob/master/TIMELINE.md))
216
-
217
-
218
-
219
- #### Report Example - Updates
220
117
 
221
- Your repos in reverse chronological order by last commit. Results in:
222
118
 
223
- ---
224
119
 
225
- > 593 repos @ 83 orgs
226
- >
227
- > committed / pushed / updated / created
228
- >
229
- > - (1d) **yorobot/backup** ★4 - 2020-10-08 (=/=) / 2020-10-08 (=) / 2020-10-08 / 2015-04-04 - ‹› (1595 kb)
230
- > - (1d) **yorobot/logs** ★1 - 2020-10-08 (=/=) / 2020-10-08 (=) / 2020-10-08 / 2016-09-13 - ‹› (172 kb)
231
- > - (1d) **rubycoco/git** ★9 - 2020-10-08 (=/=) / 2020-10-08 (=) / 2020-10-08 / 2015-11-16 - ‹› (88 kb)
232
- > - (1d) **openfootball/football.json** ★593 - 2020-10-08 (=/=) / 2020-10-08 (=) / 2020-10-08 / 2015-09-17 - ‹› (2135 kb)
233
- > - (2d) **yorobot/workflow** ★1 - 2020-10-07 (=/=) / 2020-10-07 (=) / 2020-10-07 / 2020-09-18 - ‹› (83 kb)
234
- > - (2d) **rubycoco/webclient** ★5 - 2020-10-07 (=/=) / 2020-10-07 (=) / 2020-10-07 / 2012-06-02 - ‹› (39 kb)
235
- > - (3d) **footballcsv/belgium** ★1 - 2020-10-06 (=/=) / 2020-10-06 (=) / 2020-10-06 / 2014-07-25 - ‹› (314 kb)
236
- > - (3d) **footballcsv/england** ★105 - 2020-10-06 (=/=) / 2020-10-06 (=) / 2020-10-06 / 2014-07-23 - ‹› (8666 kb)
237
- > - (3d) **footballcsv/austria** ★1 - 2020-10-06 (=/=) / 2020-10-06 (=) / 2020-10-06 / 2018-07-16 - ‹› (91 kb)
238
- > - (3d) **footballcsv/espana** ★15 - 2020-10-06 (=/=) / 2020-10-06 (=) / 2020-10-06 / 2014-07-23 - ‹› (1107 kb)
239
- > - (3d) **footballcsv/deutschland** ★5 - 2020-10-06 (=/=) / 2020-10-06 (=) / 2020-10-06 / 2014-07-25 - ‹› (1343 kb)
240
- >
241
- > ...
120
+ ### Step 3: Generate some statistics / analytics reports
242
121
 
243
- ---
244
122
 
245
- (Live Example: [`UPDATES.md`](https://github.com/yorobot/backup/blob/master/UPDATES.md))
123
+ See the [hubba-reports gem](https://github.com/rubycoco/git/tree/master/hubba-reports) on how to use pre-built/pre-packaged ready-to-use
124
+ github statistics / analytics reports.
246
125
 
247
126
 
248
127
 
@@ -23,15 +23,14 @@ end
23
23
  require 'hubba/version' # note: let version always go first
24
24
  require 'hubba/config'
25
25
  require 'hubba/github'
26
- require 'hubba/stats'
26
+ require 'hubba/reposet'
27
27
 
28
- ## "higher level" porcelain services / helpers for easy (re)use
29
- require 'hubba/folio' ## "access layer" for reports
30
- require 'hubba/hubba'
28
+ ### update stats (github data) machinery
29
+ require 'hubba/stats'
31
30
  require 'hubba/update'
32
31
  require 'hubba/update_traffic'
33
32
 
34
- require 'hubba/reports'
33
+
35
34
 
36
35
 
37
36
  ############
@@ -42,4 +41,6 @@ end
42
41
 
43
42
 
44
43
  # say hello
45
- puts Hubba.banner if defined?($RUBYCOCO_DEBUG)
44
+ puts Hubba.banner
45
+
46
+
@@ -80,18 +80,4 @@ def self.reposet( *users, orgs: true,
80
80
  h
81
81
  end ## method reposet
82
82
 
83
-
84
- def self.stats( hash_or_path='./repos.yml' ) ## use read_stats or such - why? why not?
85
- h = if hash_or_path.is_a?( String ) ## assume it is a file path!!!
86
- path = hash_or_path
87
- YAML.load_file( path )
88
- else
89
- hash_or_path # assume its a hash / reposet already!!!
90
- end
91
-
92
- Folio.new( h ) ## wrap in "easy-access" facade / wrapper
93
- end ## method stats
94
-
95
-
96
83
  end # module Hubba
97
-
@@ -5,227 +5,16 @@ module Hubba
5
5
 
6
6
  class Stats ## todo/check: rename to GithubRepoStats or RepoStats - why? why not?
7
7
 
8
- attr_reader :data
9
-
10
8
  def initialize( full_name )
11
9
  @data = {}
12
10
  @data['full_name'] = full_name # e.g. poole/hyde etc.
13
11
 
14
- @cache = {}
15
- end
16
-
17
-
18
- def full_name() @data['full_name']; end
19
-
20
-
21
- ## note: return datetime objects (NOT strings); if not present/available return nil/null
22
- def created_at() @cache['created_at'] ||= parse_datetime( @data['created_at'] ); end
23
- def updated_at() @cache['updated_at'] ||= parse_datetime( @data['updated_at'] ); end
24
- def pushed_at() @cache['pushed_at'] ||= parse_datetime( @data['pushed_at'] ); end
25
-
26
- ## date (only) versions
27
- def created() @cache['created'] ||= parse_date( @data['created_at'] ); end
28
- def updated() @cache['updated'] ||= parse_date( @data['updated_at'] ); end
29
- def pushed() @cache['pushed'] ||= parse_date( @data['pushed_at'] ); end
30
-
31
- def size
32
- # size of repo in kb (as reported by github api)
33
- @data['size'] || 0 ## return 0 if not found - why? why not? (return nil - why? why not??)
34
- end
35
-
36
-
37
- def history
38
- @cache['history'] ||= begin
39
- if @data['history']
40
- build_history( @data['history'] )
41
- else
42
- nil
43
- end
44
- end
45
- end
46
-
47
-
48
- def stars
49
- ## return last stargazers_count entry (as number; 0 if not found)
50
- @cache['stars'] ||= history ? history[0].stars : 0
51
- end
52
-
53
-
54
- def commits() @data['commits']; end
55
-
56
- def last_commit ## convenience shortcut; get first/last commit (use [0]) or nil
57
- if @data['commits'] && @data['commits'][0]
58
- @data['commits'][0]
59
- else
60
- nil
61
- end
62
- end
63
-
64
-
65
- def committed ## last commit date (from author NOT committer)
66
- @cache['committed'] ||= parse_date( last_commit_author_date )
67
- end
68
-
69
- def committed_at() ## last commit date (from author NOT committer)
70
- @cache['committed_at'] ||= parse_datetime( last_commit_author_date )
71
- end
72
-
73
- def last_commit_author_date
74
- h = last_commit
75
- h ? h['author']['date'] : nil
12
+ @cache = {} ## keep a lookup cache - why? why not?
76
13
  end
77
14
 
78
15
 
79
- def last_commit_message ## convenience shortcut; last commit message
80
- h = last_commit
81
-
82
- committer_name = h['committer']['name']
83
- author_name = h['author']['name']
84
- message = h['message']
85
-
86
- buf = ""
87
- buf << message
88
- buf << " by #{author_name}"
89
-
90
- if committer_name != author_name
91
- buf << " w/ #{committer_name}"
92
- end
93
- end # method commit_message
94
-
95
-
96
-
97
- ###
98
- # helpers
99
- def parse_datetime( str ) str ? DateTime.strptime( str, '%Y-%m-%dT%H:%M:%S') : nil; end
100
- def parse_date( str ) str ? Date.strptime( str, '%Y-%m-%d') : nil; end
101
-
102
- ########
103
- ## build history items (structs)
104
-
105
- class HistoryItem
106
-
107
- attr_reader :date, :stars ## read-only attributes
108
- attr_accessor :prev, :next ## read/write attributes (for double linked list/nodes/items)
109
-
110
- def initialize( date:, stars: )
111
- @date = date
112
- @stars = stars
113
- @next = nil
114
- end
115
-
116
- ## link items (append item at the end/tail)
117
- def append( item )
118
- @next = item
119
- item.prev = self
120
- end
121
-
122
- def diff_days
123
- if @next
124
- ## note: use jd=julian days for calculation
125
- @date.jd - @next.date.jd
126
- else
127
- nil ## last item (tail)
128
- end
129
- end
130
-
131
- def diff_stars
132
- if @next
133
- @stars - @next.stars
134
- else
135
- nil ## last item (tail)
136
- end
137
- end
138
- end ## class HistoryItem
139
-
140
-
141
- def build_history( timeseries )
142
- items = []
143
-
144
- keys = timeseries.keys.sort.reverse ## newest (latest) items first
145
- keys.each do |key|
146
- h = timeseries[ key ]
147
-
148
- item = HistoryItem.new(
149
- date: Date.strptime( key, '%Y-%m-%d' ),
150
- stars: h['stargazers_count'] || 0 )
151
-
152
- ## link items
153
- last_item = items[-1]
154
- last_item.append( item ) if last_item ## if not nil? append (note first item has no prev item)
155
-
156
- items << item
157
- end
158
-
159
- ## todo/check: return [] for empty items array (items.empty?) - why?? why not??
160
- if items.empty?
161
- nil
162
- else
163
- items
164
- end
165
- end ## method build_history
166
-
167
-
168
-
169
- def calc_diff_stars( samples: 3, days: 30 )
170
- ## samples: use n history item samples e.g. 3 samples
171
- ## days e.g. 7 days (per week), 30 days (per month)
172
-
173
- if history.nil?
174
- nil ## todo/check: return 0.0 too - why? why not?
175
- elsif history.size == 1
176
- ## just one item; CANNOT calc diff; return zero
177
- 0.0
178
- else
179
- idx = [history.size, samples].min ## calc last index
180
- last = history[idx-1]
181
- first = history[0]
182
-
183
- diff_days = first.date.jd - last.date.jd
184
- diff_stars = first.stars - last.stars
185
-
186
- ## note: use factor 1000 for fixed integer division
187
- ## converts to float at the end
188
-
189
- ## todo: check for better way (convert to float upfront - why? why not?)
190
-
191
- diff = (diff_stars * days * 1000) / diff_days
192
- ## puts "diff=#{diff}:#{diff.class.name}" ## check if it's a float
193
- (diff.to_f/1000.0)
194
- end
195
- end
196
-
197
-
198
- def history_str ## todo/check: rename/change to format_history or fmt_history - why? why not?
199
- ## returns "pretty printed" history as string buffer
200
- buf = ''
201
- buf << "[#{history.size}]: "
202
-
203
- history.each do |item|
204
- buf << "#{item.stars}"
205
-
206
- diff_stars = item.diff_stars
207
- diff_days = item.diff_days
208
- if diff_stars && diff_days ## note: last item has no diffs
209
- if diff_stars > 0 || diff_stars < 0
210
- if diff_stars > 0
211
- buf << " (+#{diff_stars}"
212
- else
213
- buf << " (#{diff_stars}"
214
- end
215
- buf << " in #{diff_days}d) "
216
- else ## diff_stars == 0
217
- buf << " (#{diff_days}d) "
218
- end
219
- end
220
- end
221
- buf
222
- end # method history_str
223
-
224
-
225
-
226
16
  ##################
227
17
  ## update
228
-
229
18
  def update_traffic( clones: nil,
230
19
  views: nil,
231
20
  paths: nil,
@@ -415,25 +204,28 @@ end # method update_traffic
415
204
 
416
205
  ########################################
417
206
  ## read / write methods / helpers
418
-
419
207
  def write
420
- basename = full_name.gsub( '/', '~' ) ## e.g. poole/hyde become poole~hyde
421
- data_dir = Hubba.config.data_dir
208
+ basename = @data['full_name'].gsub( '/', '~' ) ## e.g. poole/hyde become poole~hyde
209
+ letter = basename[0] ## use first letter as index dir e.g. p/poole~hyde
210
+ data_dir = "#{Hubba.config.data_dir}/#{letter}"
211
+ path = "#{data_dir}/#{basename}.json"
212
+
422
213
  puts " writing stats to #{basename} (#{data_dir})..."
423
214
 
424
- ## todo/fix: add FileUtils.makepath_r or such!!!
425
- File.open( "#{data_dir}/#{basename}.json", 'w:utf-8' ) do |f|
426
- f.write JSON.pretty_generate( data )
215
+ FileUtils.mkdir_p( File.dirname( path )) ## make sure path exists
216
+ File.open( path, 'w:utf-8' ) do |f|
217
+ f.write( JSON.pretty_generate( @data ))
427
218
  end
428
219
  self ## return self for (easy chaining)
429
- end
220
+ end # method write
430
221
 
431
222
 
432
223
  def read
433
224
  ## note: skip reading if file not present
434
- basename = full_name.gsub( '/', '~' ) ## e.g. poole/hyde become poole~hyde
435
- data_dir = Hubba.config.data_dir
436
- path = "#{data_dir}/#{basename}.json"
225
+ basename = @data['full_name'].gsub( '/', '~' ) ## e.g. poole/hyde become poole~hyde
226
+ letter = basename[0] ## use first letter as index dir e.g. p/poole~hyde
227
+ data_dir = "#{Hubba.config.data_dir}/#{letter}"
228
+ path = "#{data_dir}/#{basename}.json"
437
229
 
438
230
  if File.exist?( path )
439
231
  puts " reading stats from #{basename} (#{data_dir})..."
@@ -447,8 +239,7 @@ end # method update_traffic
447
239
  puts "!! WARN: - skipping reading stats from #{basename} -- file not found"
448
240
  end
449
241
  self ## return self for (easy chaining)
450
- end
451
-
242
+ end # method read
452
243
  end # class Stats
453
244
 
454
245
 
@@ -1,7 +1,7 @@
1
1
  module Hubba
2
2
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
3
- MINOR = 6
4
- PATCH = 2
3
+ MINOR = 7
4
+ PATCH = 0
5
5
  VERSION = [MAJOR,MINOR,PATCH].join('.')
6
6
 
7
7
  def self.version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hubba
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-11 00:00:00.000000000 Z
11
+ date: 2020-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: webclient
@@ -73,22 +73,14 @@ files:
73
73
  - Rakefile
74
74
  - lib/hubba.rb
75
75
  - lib/hubba/config.rb
76
- - lib/hubba/folio.rb
77
76
  - lib/hubba/github.rb
78
- - lib/hubba/hubba.rb
79
- - lib/hubba/reports.rb
77
+ - lib/hubba/reposet.rb
80
78
  - lib/hubba/stats.rb
81
79
  - lib/hubba/update.rb
82
80
  - lib/hubba/update_traffic.rb
83
81
  - lib/hubba/version.rb
84
82
  - test/helper.rb
85
- - test/stats/jekyll~minima.json
86
- - test/stats/openblockchains~awesome-blockchains.json
87
- - test/stats/opendatajson~factbook.json.json
88
- - test/stats/poole~hyde.json
89
83
  - test/test_config.rb
90
- - test/test_stats.rb
91
- - test/test_stats_tmp.rb
92
84
  homepage: https://github.com/rubycoco/git
93
85
  licenses:
94
86
  - Public Domain
@@ -1,60 +0,0 @@
1
- module Hubba
2
-
3
- class Folio # todo/check: use a different name e.g (Port)Folio, Cache, Summary, (Data)Base, Census, Catalog, Collection, Index, Register or such???
4
- class Repo ## (nested) class
5
-
6
- attr_reader :owner,
7
- :name
8
-
9
- def initialize( owner, name )
10
- @owner = owner ## rename to login, username - why? why not?
11
- @name = name ## rename to reponame ??
12
- end
13
-
14
- def full_name() "#{owner}/#{name}"; end
15
-
16
- def stats
17
- ## note: load stats on demand only (first access) for now - why? why not?
18
- @stats ||= begin
19
- stats = Stats.new( full_name )
20
- stats.read
21
- stats
22
- end
23
- end
24
-
25
- def diff
26
- @diff ||= stats.calc_diff_stars( samples: 3, days: 30 )
27
- end
28
- end # (nested) class Repo
29
-
30
-
31
- attr_reader :orgs, :repos
32
-
33
- def initialize( h )
34
- @orgs = [] # orgs and users -todo/check: use better name - logins or owners? why? why not?
35
- @repos = []
36
- add( h )
37
-
38
- puts "#{@repos.size} repos @ #{@orgs.size} orgs"
39
- end
40
-
41
- #############
42
- ## private helpes
43
- def add( h ) ## add repos.yml set
44
- h.each do |org_with_counter, names|
45
- ## remove optional number from key e.g.
46
- ## mrhydescripts (3) => mrhydescripts
47
- ## footballjs (4) => footballjs
48
- ## etc.
49
- org = org_with_counter.sub( /\([0-9]+\)/, '' ).strip
50
- repos = []
51
- names.each do |name|
52
- repo = Repo.new( org, name )
53
- repos << repo
54
- end
55
- @orgs << [org, repos]
56
- @repos += repos
57
- end
58
- end
59
- end # class Folio
60
- end # module Hubba
@@ -1,249 +0,0 @@
1
- module Hubba
2
-
3
-
4
- class Report
5
- def initialize( stats_or_hash_or_path=Hubba.stats )
6
- ## puts "[debug] Report#initialize:"
7
- ## pp stats_or_hash_or_path if stats_or_hash_or_path.is_a?( String )
8
-
9
- @stats = if stats_or_hash_or_path.is_a?( String ) ||
10
- stats_or_hash_or_path.is_a?( Hash )
11
- hash_or_path = stats_or_hash_or_path
12
- Hubba.stats( hash_or_path )
13
- else
14
- stats_or_hash_or_path ## assume Summary/Stats - todo/fix: double check!!!
15
- end
16
- end
17
-
18
- def save( path )
19
- buf = build
20
- puts "writing report >#{path}< ..."
21
- File.open( path, "w:utf-8" ) do |f|
22
- f.write( buf )
23
- end
24
- end
25
- end ## class Report
26
-
27
-
28
-
29
- class ReportSummary < Report
30
-
31
- def build
32
- ## create a (summary report)
33
- ##
34
- ## add stars, last_updates, etc.
35
- ## org description etc??
36
-
37
- ## note: orgs is orgs+users e.g. geraldb, yorobot etc
38
- buf = String.new('')
39
- buf << "# #{@stats.repos.size} repos @ #{@stats.orgs.size} orgs\n"
40
- buf << "\n"
41
-
42
-
43
- @stats.orgs.each do |org|
44
- name = org[0]
45
- repos = org[1]
46
- buf << "### #{name} _(#{repos.size})_\n"
47
- buf << "\n"
48
-
49
- ### add stats for repos
50
- entries = []
51
- repos.each do |repo|
52
- entries << "**#{repo.name}** ★#{repo.stats.stars} (#{repo.stats.size} kb)"
53
- end
54
-
55
- buf << entries.join( ' · ' ) ## use interpunct? - was: • (bullet)
56
- buf << "\n"
57
- buf << "\n"
58
- end
59
-
60
- buf
61
- end # method build
62
- end # class ReportSummary
63
-
64
-
65
-
66
- class ReportStars < Report
67
-
68
- def build
69
-
70
- ## add stars, last_updates, etc.
71
- ## org description etc??
72
-
73
- ## note: orgs is orgs+users e.g. geraldb, yorobot etc
74
- buf = String.new('')
75
- buf << "# #{@stats.repos.size} repos @ #{@stats.orgs.size} orgs\n"
76
- buf << "\n"
77
-
78
-
79
- repos = @stats.repos.sort do |l,r|
80
- ## note: use reverse sort (right,left) - e.g. most stars first
81
- r.stats.stars <=> l.stats.stars
82
- end
83
-
84
- ## pp repos
85
-
86
- repos.each_with_index do |repo,i|
87
- buf << "#{i+1}. ★#{repo.stats.stars} **#{repo.full_name}** (#{repo.stats.size} kb)\n"
88
- end
89
-
90
- buf
91
- end # method build
92
- end # class ReportStars
93
-
94
-
95
-
96
- class ReportTimeline < Report
97
-
98
- def build
99
- ## create a (timeline report)
100
-
101
- ## note: orgs is orgs+users e.g. geraldb, yorobot etc
102
- buf = String.new('')
103
- buf << "# #{@stats.repos.size} repos @ #{@stats.orgs.size} orgs\n"
104
- buf << "\n"
105
-
106
-
107
- repos = @stats.repos.sort do |l,r|
108
- ## note: use reverse sort (right,left) - e.g. most stars first
109
- ## r[:stars] <=> l[:stars]
110
-
111
- ## sort by created_at (use julian days)
112
- r.stats.created.jd <=> l.stats.created.jd
113
- end
114
-
115
-
116
- ## pp repos
117
-
118
-
119
- last_year = -1
120
- last_month = -1
121
-
122
- repos.each_with_index do |repo,i|
123
- year = repo.stats.created.year
124
- month = repo.stats.created.month
125
-
126
- if last_year != year
127
- buf << "\n## #{year}\n\n"
128
- end
129
-
130
- if last_month != month
131
- buf << "\n### #{month}\n\n"
132
- end
133
-
134
- last_year = year
135
- last_month = month
136
-
137
- buf << "- #{repo.stats.created_at.strftime('%Y-%m-%d')} ★#{repo.stats.stars} **#{repo.full_name}** (#{repo.stats.size} kb)\n"
138
- end
139
-
140
- buf
141
- end # method build
142
- end # class ReportTimeline
143
-
144
-
145
-
146
- class ReportTrending < Report
147
-
148
- def build
149
-
150
- ## note: orgs is orgs+users e.g. geraldb, yorobot etc
151
- buf = String.new('')
152
- buf << "# #{@stats.repos.size} repos @ #{@stats.orgs.size} orgs\n"
153
- buf << "\n"
154
-
155
- ###
156
- ## todo:
157
- ## use calc per month (days: 30)
158
- ## per week is too optimistic (e.g. less than one star/week e.g. 0.6 or something)
159
-
160
- repos = @stats.repos.sort do |l,r|
161
- ## note: use reverse sort (right,left) - e.g. most stars first
162
- ## r[:stars] <=> l[:stars]
163
-
164
- ## sort by created_at (use julian days)
165
- ## r[:created_at].to_date.jd <=> l[:created_at].to_date.jd
166
-
167
- res = r.diff <=> l.diff
168
- res = r.stats.stars <=> l.stats.stars if res == 0
169
- res = r.stats.created.jd <=> l.stats.created.jd if res == 0
170
- res
171
- end
172
-
173
-
174
- ## pp repos
175
-
176
-
177
- repos.each_with_index do |repo,i|
178
- if repo.diff == 0
179
- buf << "- -/- "
180
- else
181
- buf << "- #{repo.diff}/month "
182
- end
183
-
184
- buf << " ★#{repo.stats.stars} **#{repo.full_name}** (#{repo.stats.size} kb) - "
185
- buf << "#{repo.stats.history_str}\n"
186
- end
187
-
188
-
189
- buf
190
- end # method build
191
- end # class ReportTrending
192
-
193
-
194
-
195
- class ReportUpdates < Report
196
-
197
- def build
198
-
199
- ## note: orgs is orgs+users e.g. geraldb, yorobot etc
200
- buf = String.new('')
201
- buf << "# #{@stats.repos.size} repos @ #{@stats.orgs.size} orgs\n"
202
- buf << "\n"
203
-
204
- repos = @stats.repos.sort do |l,r|
205
- r.stats.committed.jd <=> l.stats.committed.jd
206
- end
207
-
208
- ## pp repos
209
-
210
-
211
- buf << "committed / pushed / updated / created\n\n"
212
-
213
- today = Date.today
214
-
215
- repos.each_with_index do |repo,i|
216
-
217
- days_ago = today.jd - repo.stats.committed.jd
218
-
219
- diff1 = repo.stats.committed.jd - repo.stats.pushed.jd
220
- diff2 = repo.stats.committed.jd - repo.stats.updated.jd
221
- diff3 = repo.stats.pushed.jd - repo.stats.updated.jd
222
-
223
- buf << "- (#{days_ago}d) **#{repo.full_name}** ★#{repo.stats.stars} - "
224
- buf << "#{repo.stats.committed} "
225
- buf << "("
226
- buf << (diff1==0 ? '=' : "#{diff1}d")
227
- buf << "/"
228
- buf << (diff2==0 ? '=' : "#{diff2}d")
229
- buf << ")"
230
- buf << " / "
231
- buf << "#{repo.stats.pushed} "
232
- buf << "("
233
- buf << (diff3==0 ? '=' : "#{diff3}d")
234
- buf << ")"
235
- buf << " / "
236
- buf << "#{repo.stats.updated} / "
237
- buf << "#{repo.stats.created} - "
238
- buf << "‹#{repo.stats.last_commit_message}›"
239
- buf << " (#{repo.stats.size} kb)"
240
- buf << "\n"
241
- end
242
-
243
-
244
- buf
245
- end # method build
246
- end # class ReportUpdates
247
-
248
-
249
- end # module Hubba
@@ -1,25 +0,0 @@
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
- }
@@ -1,27 +0,0 @@
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
- }
@@ -1,39 +0,0 @@
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
- }
@@ -1,21 +0,0 @@
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,125 +0,0 @@
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
- Hubba.config.data_dir = "#{Hubba.root}/test/stats"
21
- stats.read
22
-
23
- assert_equal 321, stats.size
24
- assert_equal 717, stats.stars
25
- assert_equal 717, stats.history[0].stars
26
- assert_equal 1, stats.history.size
27
-
28
- assert_equal Date.new(2018, 2, 12 ), stats.history[0].date
29
-
30
- assert_nil stats.history[0].diff_days
31
-
32
- assert_equal Date.new(2018, 2, 21 ), stats.committed
33
- assert_equal Date.new(2016, 5, 20 ), stats.created
34
- assert_equal Date.new(2018, 2, 11 ), stats.updated
35
- assert_equal Date.new(2018, 2, 7 ), stats.pushed
36
-
37
- assert_equal DateTime.new(2018, 2, 21, 19, 35, 59 ), stats.committed_at
38
- assert_equal DateTime.new(2016, 5, 20, 23, 7, 56 ), stats.created_at
39
- assert_equal DateTime.new(2018, 2, 11, 16, 13, 33 ), stats.updated_at
40
- assert_equal DateTime.new(2018, 2, 7, 22, 14, 11 ), stats.pushed_at
41
-
42
-
43
- pp stats.last_commit
44
- pp stats.last_commit_message
45
- pp stats.history_str ## pp history pretty printed to string (buffer)
46
- end
47
-
48
-
49
-
50
- def test_awesome_blockchains
51
-
52
- stats = Hubba::Stats.new( 'openblockchains/awesome-blockchains' )
53
-
54
- assert_equal 0, stats.size
55
- assert_equal 0, stats.stars
56
- assert_nil stats.history
57
-
58
- Hubba.config.data_dir = "#{Hubba.root}/test/stats"
59
- stats.read
60
-
61
- assert_equal 1620, stats.size
62
- assert_equal 1526, stats.stars
63
- assert_equal 1526, stats.history[0].stars
64
- assert_equal 1411, stats.history[1].stars
65
- assert_equal 1084, stats.history[2].stars
66
- assert_equal 1084, stats.history[-1].stars
67
- assert_equal 3, stats.history.size
68
-
69
- assert_equal Date.new(2018, 2, 8 ), stats.history[0].date
70
- assert_equal Date.new(2018, 1, 28 ), stats.history[1].date
71
- assert_equal Date.new(2017, 12, 10 ), stats.history[2].date
72
-
73
- assert_equal 11, stats.history[0].diff_days
74
- assert_equal 49, stats.history[1].diff_days
75
- assert_nil stats.history[2].diff_days
76
-
77
- assert_equal 115, stats.history[0].diff_stars
78
- assert_equal 327, stats.history[1].diff_stars
79
- assert_nil stats.history[2].diff_stars
80
-
81
- assert_equal 221.0, stats.calc_diff_stars ## defaults to samples: 3, days: 30
82
- assert_equal 51.566, stats.calc_diff_stars( samples: 5, days: 7 )
83
-
84
- pp stats.history_str ## pp history pretty printed to string (buffer)
85
- end
86
-
87
-
88
- def test_factbook_json
89
-
90
- stats = Hubba::Stats.new( 'opendatajson/factbook.json' )
91
-
92
- assert_equal 0, stats.size
93
- assert_equal 0, stats.stars
94
- assert_nil stats.history
95
-
96
- Hubba.config.data_dir = "#{Hubba.root}/test/stats"
97
- stats.read
98
-
99
- assert_equal 7355, stats.size
100
- assert_equal 539, stats.stars
101
- assert_equal 539, stats.history[0].stars
102
- assert_equal 536, stats.history[1].stars
103
- assert_equal 533, stats.history[2].stars
104
- assert_equal 457, stats.history[-1].stars
105
- assert_equal 7, stats.history.size
106
-
107
- assert_equal Date.new(2018, 2, 8 ), stats.history[0].date
108
- assert_equal Date.new(2018, 1, 28 ), stats.history[1].date
109
- assert_equal Date.new(2017, 12, 10 ), stats.history[2].date
110
-
111
- assert_equal 11, stats.history[0].diff_days
112
- assert_equal 49, stats.history[1].diff_days
113
- assert_nil stats.history[-1].diff_days
114
-
115
- assert_equal 3, stats.history[0].diff_stars
116
- assert_equal 3, stats.history[1].diff_stars
117
- assert_nil stats.history[-1].diff_stars
118
-
119
- assert_equal 3.0, stats.calc_diff_stars ## defaults to samples: 3, days: 30
120
- assert_equal 1.012, stats.calc_diff_stars( samples: 5, days: 7 )
121
-
122
- pp stats.history_str ## pp history pretty printed to string (buffer)
123
- end
124
-
125
- end # class TestStats
@@ -1,44 +0,0 @@
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
13
- end
14
-
15
- def test_stats
16
- repos = [
17
- 'poole/hyde',
18
- 'jekyll/minima'
19
- ]
20
-
21
-
22
- repos.each do |repo|
23
- stats = Hubba::Stats.new( repo )
24
-
25
- Hubba.config.data_dir = "#{Hubba.root}/test/stats"
26
- stats.read()
27
-
28
- puts "stars before fetch: #{stats.stars}"
29
- puts "size before fetch: #{stats.size} kb"
30
-
31
- ## note/todo: enable for "live" online testing
32
- ## @gh.update( stats )
33
-
34
- puts "stars after fetch: #{stats.stars}"
35
- puts "size after fetch: #{stats.size} kb"
36
-
37
- Hubba.config.data_dir = './tmp'
38
- stats.write()
39
- end
40
-
41
- assert true # for now everything ok if we get here
42
- end
43
-
44
- end # class TestStatsTmp