how_is 18.0.4 → 18.0.5

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.
data/exe/how_is CHANGED
@@ -8,11 +8,9 @@ require "how_is/cli"
8
8
  begin
9
9
  result = HowIs::CLI.parse(ARGV)
10
10
  rescue HowIs::CLI::OptionsError => e
11
- if ENV['SHOW_TRACE']
12
- raise
13
- else
14
- abort "Error: #{e.message}"
15
- end
11
+ raise if ENV["SHOW_TRACE"]
12
+
13
+ abort "Error: #{e.message}"
16
14
  end
17
15
 
18
16
  options = result[:options]
@@ -45,10 +43,7 @@ begin
45
43
  )
46
44
  end
47
45
  rescue => e
48
- if ENV['SHOW_TRACE']
49
- raise
50
- else
51
- abort "Error: #{e.message}"
52
- end
53
- end
46
+ raise if ENV["SHOW_TRACE"]
54
47
 
48
+ abort "Error: #{e.message}"
49
+ end
@@ -0,0 +1,78 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.github.com/repos/how-is/example-repository/commits?since=2017-01-01
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1
12
+ Accept-Charset:
13
+ - utf-8
14
+ User-Agent:
15
+ - Github API Ruby Gem 0.17.0
16
+ Accept-Encoding:
17
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Server:
24
+ - GitHub.com
25
+ Date:
26
+ - Sat, 05 Aug 2017 21:05:34 GMT
27
+ Content-Type:
28
+ - application/json; charset=utf-8
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Status:
32
+ - 200 OK
33
+ X-Ratelimit-Limit:
34
+ - '60'
35
+ X-Ratelimit-Remaining:
36
+ - '6'
37
+ X-Ratelimit-Reset:
38
+ - '1501967489'
39
+ Cache-Control:
40
+ - public, max-age=60, s-maxage=60
41
+ Vary:
42
+ - Accept
43
+ Etag:
44
+ - W/"c4e64de253131e8983284594017e505c"
45
+ Last-Modified:
46
+ - Sat, 05 Aug 2017 20:39:01 GMT
47
+ X-Github-Media-Type:
48
+ - github.v3; format=json
49
+ Access-Control-Expose-Headers:
50
+ - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset,
51
+ X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
52
+ Access-Control-Allow-Origin:
53
+ - "*"
54
+ Content-Security-Policy:
55
+ - default-src 'none'
56
+ Strict-Transport-Security:
57
+ - max-age=31536000; includeSubdomains; preload
58
+ X-Content-Type-Options:
59
+ - nosniff
60
+ X-Frame-Options:
61
+ - deny
62
+ X-Xss-Protection:
63
+ - 1; mode=block
64
+ X-Runtime-Rack:
65
+ - '0.046194'
66
+ X-Github-Request-Id:
67
+ - DA1A:795E:9C82C1:19614C6:5986331E
68
+ body:
69
+ encoding: ASCII-8BIT
70
+ string: '[{"sha":"40c01ab6ebec6cbd8ad9e521a732f941c169e557","commit":{"author":{"name":"Ellen
71
+ Marie Dash","email":"me@duckie.co","date":"2017-08-05T20:39:01Z"},"committer":{"name":"Ellen
72
+ Marie Dash","email":"me@duckie.co","date":"2017-08-05T20:39:01Z"},"message":"meep","tree":{"sha":"6911e0637822f44b83f04f47821adab56fdbc0b9","url":"https://api.github.com/repos/how-is/example-repository/git/trees/6911e0637822f44b83f04f47821adab56fdbc0b9"},"url":"https://api.github.com/repos/how-is/example-repository/git/commits/40c01ab6ebec6cbd8ad9e521a732f941c169e557","comment_count":0},"url":"https://api.github.com/repos/how-is/example-repository/commits/40c01ab6ebec6cbd8ad9e521a732f941c169e557","html_url":"https://github.com/how-is/example-repository/commit/40c01ab6ebec6cbd8ad9e521a732f941c169e557","comments_url":"https://api.github.com/repos/how-is/example-repository/commits/40c01ab6ebec6cbd8ad9e521a732f941c169e557/comments","author":{"login":"duckinator","id":39698,"avatar_url":"https://avatars3.githubusercontent.com/u/39698?v=4","gravatar_id":"","url":"https://api.github.com/users/duckinator","html_url":"https://github.com/duckinator","followers_url":"https://api.github.com/users/duckinator/followers","following_url":"https://api.github.com/users/duckinator/following{/other_user}","gists_url":"https://api.github.com/users/duckinator/gists{/gist_id}","starred_url":"https://api.github.com/users/duckinator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/duckinator/subscriptions","organizations_url":"https://api.github.com/users/duckinator/orgs","repos_url":"https://api.github.com/users/duckinator/repos","events_url":"https://api.github.com/users/duckinator/events{/privacy}","received_events_url":"https://api.github.com/users/duckinator/received_events","type":"User","site_admin":false},"committer":{"login":"duckinator","id":39698,"avatar_url":"https://avatars3.githubusercontent.com/u/39698?v=4","gravatar_id":"","url":"https://api.github.com/users/duckinator","html_url":"https://github.com/duckinator","followers_url":"https://api.github.com/users/duckinator/followers","following_url":"https://api.github.com/users/duckinator/following{/other_user}","gists_url":"https://api.github.com/users/duckinator/gists{/gist_id}","starred_url":"https://api.github.com/users/duckinator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/duckinator/subscriptions","organizations_url":"https://api.github.com/users/duckinator/orgs","repos_url":"https://api.github.com/users/duckinator/repos","events_url":"https://api.github.com/users/duckinator/events{/privacy}","received_events_url":"https://api.github.com/users/duckinator/received_events","type":"User","site_admin":false},"parents":[{"sha":"3794aa1c4b76623748faf280abe5760b76823162","url":"https://api.github.com/repos/how-is/example-repository/commits/3794aa1c4b76623748faf280abe5760b76823162","html_url":"https://github.com/how-is/example-repository/commit/3794aa1c4b76623748faf280abe5760b76823162"}]},{"sha":"3794aa1c4b76623748faf280abe5760b76823162","commit":{"author":{"name":"fake
73
+ author","email":"fake@duckinator.net","date":"2017-08-05T20:23:10Z"},"committer":{"name":"fake
74
+ author","email":"fake@duckinator.net","date":"2017-08-05T20:23:10Z"},"message":"test
75
+ commit","tree":{"sha":"8286e548e330cfe01efcf7189f4df1fa53e777a7","url":"https://api.github.com/repos/how-is/example-repository/git/trees/8286e548e330cfe01efcf7189f4df1fa53e777a7"},"url":"https://api.github.com/repos/how-is/example-repository/git/commits/3794aa1c4b76623748faf280abe5760b76823162","comment_count":0},"url":"https://api.github.com/repos/how-is/example-repository/commits/3794aa1c4b76623748faf280abe5760b76823162","html_url":"https://github.com/how-is/example-repository/commit/3794aa1c4b76623748faf280abe5760b76823162","comments_url":"https://api.github.com/repos/how-is/example-repository/commits/3794aa1c4b76623748faf280abe5760b76823162/comments","author":null,"committer":null,"parents":[{"sha":"9e29405efa433529b86722542b8fb4b34dfd9edd","url":"https://api.github.com/repos/how-is/example-repository/commits/9e29405efa433529b86722542b8fb4b34dfd9edd","html_url":"https://github.com/how-is/example-repository/commit/9e29405efa433529b86722542b8fb4b34dfd9edd"}]}]'
76
+ http_version:
77
+ recorded_at: Sat, 05 Aug 2017 21:05:34 GMT
78
+ recorded_with: VCR 3.0.3
@@ -0,0 +1,219 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.github.com/repos/how-is/example-repository/commits?since=2017-01-01
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1
12
+ Accept-Charset:
13
+ - utf-8
14
+ User-Agent:
15
+ - Github API Ruby Gem 0.17.0
16
+ Accept-Encoding:
17
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Server:
24
+ - GitHub.com
25
+ Date:
26
+ - Sat, 05 Aug 2017 21:08:49 GMT
27
+ Content-Type:
28
+ - application/json; charset=utf-8
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Status:
32
+ - 200 OK
33
+ X-Ratelimit-Limit:
34
+ - '60'
35
+ X-Ratelimit-Remaining:
36
+ - '5'
37
+ X-Ratelimit-Reset:
38
+ - '1501967489'
39
+ Cache-Control:
40
+ - public, max-age=60, s-maxage=60
41
+ Vary:
42
+ - Accept
43
+ Etag:
44
+ - W/"c4e64de253131e8983284594017e505c"
45
+ Last-Modified:
46
+ - Sat, 05 Aug 2017 20:39:01 GMT
47
+ X-Github-Media-Type:
48
+ - github.v3; format=json
49
+ Access-Control-Expose-Headers:
50
+ - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset,
51
+ X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
52
+ Access-Control-Allow-Origin:
53
+ - "*"
54
+ Content-Security-Policy:
55
+ - default-src 'none'
56
+ Strict-Transport-Security:
57
+ - max-age=31536000; includeSubdomains; preload
58
+ X-Content-Type-Options:
59
+ - nosniff
60
+ X-Frame-Options:
61
+ - deny
62
+ X-Xss-Protection:
63
+ - 1; mode=block
64
+ X-Runtime-Rack:
65
+ - '0.044265'
66
+ X-Github-Request-Id:
67
+ - DA58:795D:BB06DF:178487C:598633E1
68
+ body:
69
+ encoding: ASCII-8BIT
70
+ string: '[{"sha":"40c01ab6ebec6cbd8ad9e521a732f941c169e557","commit":{"author":{"name":"Ellen
71
+ Marie Dash","email":"me@duckie.co","date":"2017-08-05T20:39:01Z"},"committer":{"name":"Ellen
72
+ Marie Dash","email":"me@duckie.co","date":"2017-08-05T20:39:01Z"},"message":"meep","tree":{"sha":"6911e0637822f44b83f04f47821adab56fdbc0b9","url":"https://api.github.com/repos/how-is/example-repository/git/trees/6911e0637822f44b83f04f47821adab56fdbc0b9"},"url":"https://api.github.com/repos/how-is/example-repository/git/commits/40c01ab6ebec6cbd8ad9e521a732f941c169e557","comment_count":0},"url":"https://api.github.com/repos/how-is/example-repository/commits/40c01ab6ebec6cbd8ad9e521a732f941c169e557","html_url":"https://github.com/how-is/example-repository/commit/40c01ab6ebec6cbd8ad9e521a732f941c169e557","comments_url":"https://api.github.com/repos/how-is/example-repository/commits/40c01ab6ebec6cbd8ad9e521a732f941c169e557/comments","author":{"login":"duckinator","id":39698,"avatar_url":"https://avatars3.githubusercontent.com/u/39698?v=4","gravatar_id":"","url":"https://api.github.com/users/duckinator","html_url":"https://github.com/duckinator","followers_url":"https://api.github.com/users/duckinator/followers","following_url":"https://api.github.com/users/duckinator/following{/other_user}","gists_url":"https://api.github.com/users/duckinator/gists{/gist_id}","starred_url":"https://api.github.com/users/duckinator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/duckinator/subscriptions","organizations_url":"https://api.github.com/users/duckinator/orgs","repos_url":"https://api.github.com/users/duckinator/repos","events_url":"https://api.github.com/users/duckinator/events{/privacy}","received_events_url":"https://api.github.com/users/duckinator/received_events","type":"User","site_admin":false},"committer":{"login":"duckinator","id":39698,"avatar_url":"https://avatars3.githubusercontent.com/u/39698?v=4","gravatar_id":"","url":"https://api.github.com/users/duckinator","html_url":"https://github.com/duckinator","followers_url":"https://api.github.com/users/duckinator/followers","following_url":"https://api.github.com/users/duckinator/following{/other_user}","gists_url":"https://api.github.com/users/duckinator/gists{/gist_id}","starred_url":"https://api.github.com/users/duckinator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/duckinator/subscriptions","organizations_url":"https://api.github.com/users/duckinator/orgs","repos_url":"https://api.github.com/users/duckinator/repos","events_url":"https://api.github.com/users/duckinator/events{/privacy}","received_events_url":"https://api.github.com/users/duckinator/received_events","type":"User","site_admin":false},"parents":[{"sha":"3794aa1c4b76623748faf280abe5760b76823162","url":"https://api.github.com/repos/how-is/example-repository/commits/3794aa1c4b76623748faf280abe5760b76823162","html_url":"https://github.com/how-is/example-repository/commit/3794aa1c4b76623748faf280abe5760b76823162"}]},{"sha":"3794aa1c4b76623748faf280abe5760b76823162","commit":{"author":{"name":"fake
73
+ author","email":"fake@duckinator.net","date":"2017-08-05T20:23:10Z"},"committer":{"name":"fake
74
+ author","email":"fake@duckinator.net","date":"2017-08-05T20:23:10Z"},"message":"test
75
+ commit","tree":{"sha":"8286e548e330cfe01efcf7189f4df1fa53e777a7","url":"https://api.github.com/repos/how-is/example-repository/git/trees/8286e548e330cfe01efcf7189f4df1fa53e777a7"},"url":"https://api.github.com/repos/how-is/example-repository/git/commits/3794aa1c4b76623748faf280abe5760b76823162","comment_count":0},"url":"https://api.github.com/repos/how-is/example-repository/commits/3794aa1c4b76623748faf280abe5760b76823162","html_url":"https://github.com/how-is/example-repository/commit/3794aa1c4b76623748faf280abe5760b76823162","comments_url":"https://api.github.com/repos/how-is/example-repository/commits/3794aa1c4b76623748faf280abe5760b76823162/comments","author":null,"committer":null,"parents":[{"sha":"9e29405efa433529b86722542b8fb4b34dfd9edd","url":"https://api.github.com/repos/how-is/example-repository/commits/9e29405efa433529b86722542b8fb4b34dfd9edd","html_url":"https://github.com/how-is/example-repository/commit/9e29405efa433529b86722542b8fb4b34dfd9edd"}]}]'
76
+ http_version:
77
+ recorded_at: Sat, 05 Aug 2017 21:08:49 GMT
78
+ - request:
79
+ method: get
80
+ uri: https://api.github.com/repos/how-is/example-repository/commits?author=me@duckie.co&until=2017-01-01
81
+ body:
82
+ encoding: US-ASCII
83
+ string: ''
84
+ headers:
85
+ Accept:
86
+ - application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1
87
+ Accept-Charset:
88
+ - utf-8
89
+ User-Agent:
90
+ - Github API Ruby Gem 0.17.0
91
+ Accept-Encoding:
92
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
93
+ response:
94
+ status:
95
+ code: 200
96
+ message: OK
97
+ headers:
98
+ Server:
99
+ - GitHub.com
100
+ Date:
101
+ - Sat, 05 Aug 2017 21:08:50 GMT
102
+ Content-Type:
103
+ - application/json; charset=utf-8
104
+ Transfer-Encoding:
105
+ - chunked
106
+ Status:
107
+ - 200 OK
108
+ X-Ratelimit-Limit:
109
+ - '60'
110
+ X-Ratelimit-Remaining:
111
+ - '4'
112
+ X-Ratelimit-Reset:
113
+ - '1501967489'
114
+ Cache-Control:
115
+ - public, max-age=60, s-maxage=60
116
+ Vary:
117
+ - Accept
118
+ Etag:
119
+ - W/"63ec50619f12827a37594ae87db65a6d"
120
+ Last-Modified:
121
+ - Sun, 07 Aug 2016 03:52:54 GMT
122
+ X-Github-Media-Type:
123
+ - github.v3; format=json
124
+ Access-Control-Expose-Headers:
125
+ - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset,
126
+ X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
127
+ Access-Control-Allow-Origin:
128
+ - "*"
129
+ Content-Security-Policy:
130
+ - default-src 'none'
131
+ Strict-Transport-Security:
132
+ - max-age=31536000; includeSubdomains; preload
133
+ X-Content-Type-Options:
134
+ - nosniff
135
+ X-Frame-Options:
136
+ - deny
137
+ X-Xss-Protection:
138
+ - 1; mode=block
139
+ X-Runtime-Rack:
140
+ - '0.044928'
141
+ X-Github-Request-Id:
142
+ - DA59:795E:9CC15F:196C854:598633E2
143
+ body:
144
+ encoding: ASCII-8BIT
145
+ string: '[{"sha":"9e29405efa433529b86722542b8fb4b34dfd9edd","commit":{"author":{"name":"Ellen
146
+ Marie Dash","email":"me@duckie.co","date":"2016-08-07T03:52:54Z"},"committer":{"name":"Ellen
147
+ Marie Dash","email":"me@duckie.co","date":"2016-08-07T03:52:54Z"},"message":"Initial
148
+ commit","tree":{"sha":"7bee2a10cc8c7c036d5006fa0aacadd869d09c4e","url":"https://api.github.com/repos/how-is/example-repository/git/trees/7bee2a10cc8c7c036d5006fa0aacadd869d09c4e"},"url":"https://api.github.com/repos/how-is/example-repository/git/commits/9e29405efa433529b86722542b8fb4b34dfd9edd","comment_count":0},"url":"https://api.github.com/repos/how-is/example-repository/commits/9e29405efa433529b86722542b8fb4b34dfd9edd","html_url":"https://github.com/how-is/example-repository/commit/9e29405efa433529b86722542b8fb4b34dfd9edd","comments_url":"https://api.github.com/repos/how-is/example-repository/commits/9e29405efa433529b86722542b8fb4b34dfd9edd/comments","author":{"login":"duckinator","id":39698,"avatar_url":"https://avatars3.githubusercontent.com/u/39698?v=4","gravatar_id":"","url":"https://api.github.com/users/duckinator","html_url":"https://github.com/duckinator","followers_url":"https://api.github.com/users/duckinator/followers","following_url":"https://api.github.com/users/duckinator/following{/other_user}","gists_url":"https://api.github.com/users/duckinator/gists{/gist_id}","starred_url":"https://api.github.com/users/duckinator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/duckinator/subscriptions","organizations_url":"https://api.github.com/users/duckinator/orgs","repos_url":"https://api.github.com/users/duckinator/repos","events_url":"https://api.github.com/users/duckinator/events{/privacy}","received_events_url":"https://api.github.com/users/duckinator/received_events","type":"User","site_admin":false},"committer":{"login":"duckinator","id":39698,"avatar_url":"https://avatars3.githubusercontent.com/u/39698?v=4","gravatar_id":"","url":"https://api.github.com/users/duckinator","html_url":"https://github.com/duckinator","followers_url":"https://api.github.com/users/duckinator/followers","following_url":"https://api.github.com/users/duckinator/following{/other_user}","gists_url":"https://api.github.com/users/duckinator/gists{/gist_id}","starred_url":"https://api.github.com/users/duckinator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/duckinator/subscriptions","organizations_url":"https://api.github.com/users/duckinator/orgs","repos_url":"https://api.github.com/users/duckinator/repos","events_url":"https://api.github.com/users/duckinator/events{/privacy}","received_events_url":"https://api.github.com/users/duckinator/received_events","type":"User","site_admin":false},"parents":[]}]'
149
+ http_version:
150
+ recorded_at: Sat, 05 Aug 2017 21:08:50 GMT
151
+ - request:
152
+ method: get
153
+ uri: https://api.github.com/repos/how-is/example-repository/commits?author=fake@duckinator.net&until=2017-01-01
154
+ body:
155
+ encoding: US-ASCII
156
+ string: ''
157
+ headers:
158
+ Accept:
159
+ - application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1
160
+ Accept-Charset:
161
+ - utf-8
162
+ User-Agent:
163
+ - Github API Ruby Gem 0.17.0
164
+ Accept-Encoding:
165
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
166
+ response:
167
+ status:
168
+ code: 200
169
+ message: OK
170
+ headers:
171
+ Server:
172
+ - GitHub.com
173
+ Date:
174
+ - Sat, 05 Aug 2017 21:08:51 GMT
175
+ Content-Type:
176
+ - application/json; charset=utf-8
177
+ Content-Length:
178
+ - '2'
179
+ Status:
180
+ - 200 OK
181
+ X-Ratelimit-Limit:
182
+ - '60'
183
+ X-Ratelimit-Remaining:
184
+ - '3'
185
+ X-Ratelimit-Reset:
186
+ - '1501967489'
187
+ Cache-Control:
188
+ - public, max-age=60, s-maxage=60
189
+ Vary:
190
+ - Accept
191
+ Etag:
192
+ - '"fafd06a937c504cece6726ba7201b0a1"'
193
+ X-Github-Media-Type:
194
+ - github.v3; format=json
195
+ Access-Control-Expose-Headers:
196
+ - ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset,
197
+ X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
198
+ Access-Control-Allow-Origin:
199
+ - "*"
200
+ Content-Security-Policy:
201
+ - default-src 'none'
202
+ Strict-Transport-Security:
203
+ - max-age=31536000; includeSubdomains; preload
204
+ X-Content-Type-Options:
205
+ - nosniff
206
+ X-Frame-Options:
207
+ - deny
208
+ X-Xss-Protection:
209
+ - 1; mode=block
210
+ X-Runtime-Rack:
211
+ - '0.033466'
212
+ X-Github-Request-Id:
213
+ - DA5A:795A:69CBD4:E6BF0D:598633E2
214
+ body:
215
+ encoding: UTF-8
216
+ string: "[]"
217
+ http_version:
218
+ recorded_at: Sat, 05 Aug 2017 21:08:51 GMT
219
+ recorded_with: VCR 3.0.3
data/how_is.gemspec CHANGED
@@ -31,5 +31,6 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency "timecop", "~> 0.8.1"
32
32
  spec.add_development_dependency "vcr", "~> 3.0"
33
33
  spec.add_development_dependency "webmock"
34
- spec.add_development_dependency "rubocop", "~> 0.47.0"
34
+ spec.add_development_dependency "rubocop", "~> 0.49.1"
35
+ spec.add_development_dependency "github_changelog_generator"
35
36
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'contracts'
4
- require 'ostruct'
5
- require 'date'
6
- require 'json'
3
+ require "contracts"
4
+ require "ostruct"
5
+ require "date"
6
+ require "json"
7
7
 
8
8
  class HowIs
9
9
  ##
@@ -11,11 +11,12 @@ class HowIs
11
11
  class Analysis < OpenStruct
12
12
  end
13
13
 
14
+ # Creates Analysis objects with input data formatted in useful ways.
14
15
  class Analyzer
15
16
  include Contracts::Core
16
17
 
17
18
  ##
18
- # Raised when attempting to export to an unsupported format.
19
+ # Raised when attempting to import to an unsupported format.
19
20
  class UnsupportedImportFormat < StandardError
20
21
  def initialize(format)
21
22
  super("Unsupported import format: #{format}")
@@ -23,7 +24,7 @@ class HowIs
23
24
  end
24
25
 
25
26
  ##
26
- # Generates and returns an analysis.i
27
+ # Generates and returns an analysis.
27
28
  #
28
29
  # @param data [Fetcher::Results] The results gathered by Fetcher.
29
30
  # @param analysis_class (You don't need this.) A class to use instead of
@@ -43,7 +44,7 @@ class HowIs
43
44
  number_of_pulls: pulls.length,
44
45
 
45
46
  issues_with_label: with_label_links(num_with_label(issues), data.repository),
46
- issues_with_no_label: {'link' => nil, 'total' => num_with_no_label(issues)},
47
+ issues_with_no_label: {"link" => nil, "total" => num_with_no_label(issues)},
47
48
 
48
49
  average_issue_age: average_age_for(issues),
49
50
  average_pull_age: average_age_for(pulls),
@@ -64,15 +65,15 @@ class HowIs
64
65
  # @param data [Hash] The hash to generate an Analysis from.
65
66
  def self.from_hash(data)
66
67
  hash = data.map { |k, v|
67
- v = DateTime.parse(v) if k.end_with?('_date')
68
+ v = DateTime.parse(v) if k.end_with?("_date")
68
69
 
69
70
  [k, v]
70
71
  }.to_h
71
72
 
72
73
  hash.keys.each do |key|
73
- next unless hash[key].is_a?(Hash) && hash[key]['date']
74
+ next unless hash[key].is_a?(Hash) && hash[key]["date"]
74
75
 
75
- hash[key]['date'] = DateTime.parse(hash[key]['date'])
76
+ hash[key]["date"] = DateTime.parse(hash[key]["date"])
76
77
  end
77
78
 
78
79
  Analysis.new(hash)
@@ -90,10 +91,10 @@ class HowIs
90
91
 
91
92
  hash = Hash.new(0)
92
93
  issues_or_pulls.each do |iop|
93
- next unless iop['labels']
94
+ next unless iop["labels"]
94
95
 
95
- iop['labels'].each do |label|
96
- hash[label['name']] += 1
96
+ iop["labels"].each do |label|
97
+ hash[label["name"]] += 1
97
98
  end
98
99
  end
99
100
  hash
@@ -101,16 +102,16 @@ class HowIs
101
102
 
102
103
  # Returns the number of issues with no label.
103
104
  def num_with_no_label(issues)
104
- issues.select { |x| x['labels'].empty? }.length
105
+ issues.select { |x| x["labels"].empty? }.length
105
106
  end
106
107
 
107
108
  # Given an Array of dates, average the timestamps and return the date that
108
109
  # represents.
109
110
  def average_date_for(issues_or_pulls)
110
- timestamps = issues_or_pulls.map { |iop| Date.parse(iop['created_at']).strftime('%s').to_i }
111
+ timestamps = issues_or_pulls.map { |iop| Date.parse(iop["created_at"]).strftime("%s").to_i }
111
112
  average_timestamp = timestamps.reduce(:+) / issues_or_pulls.length
112
113
 
113
- DateTime.strptime(average_timestamp.to_s, '%s')
114
+ DateTime.strptime(average_timestamp.to_s, "%s")
114
115
  end
115
116
 
116
117
  # Given an Array of issues or pulls, return the average age of them.
@@ -118,32 +119,11 @@ class HowIs
118
119
  def average_age_for(issues_or_pulls)
119
120
  return nil if issues_or_pulls.empty?
120
121
 
121
- ages = issues_or_pulls.map { |iop| time_ago_in_seconds(iop['created_at']) }
122
- raw_average = ages.reduce(:+) / ages.length
122
+ ages = issues_or_pulls.map { |iop| time_ago_in_seconds(iop["created_at"]) }
123
+ average_age_in_seconds = ages.reduce(:+) / ages.length
123
124
 
124
- seconds_in_a_year = 31_556_926
125
- seconds_in_a_month = 2_629_743
126
- seconds_in_a_week = 604_800
127
- seconds_in_a_day = 86_400
128
-
129
- years = raw_average / seconds_in_a_year
130
- years_remainder = raw_average % seconds_in_a_year
131
-
132
- months = years_remainder / seconds_in_a_month
133
- months_remainder = years_remainder % seconds_in_a_month
134
-
135
- weeks = months_remainder / seconds_in_a_week
136
- weeks_remainder = months_remainder % seconds_in_a_week
137
-
138
- days = weeks_remainder / seconds_in_a_day
139
-
140
- values = [
141
- [years, "year"],
142
- [months, "month"],
143
- [weeks, "week"],
144
- [days, "day"],
145
- ].reject { |(v, _)| v == 0 }.map { |(v, k)|
146
- k += 's' if v != 1
125
+ values = period_pairs_for(average_age_in_seconds).reject { |(v, _)| v.zero? }.map { |(v, k)|
126
+ k += "s" if v != 1
147
127
  [v, k]
148
128
  }
149
129
 
@@ -160,7 +140,7 @@ class HowIs
160
140
  end
161
141
 
162
142
  def sort_iops_by_created_at(issues_or_pulls)
163
- issues_or_pulls.sort_by { |x| DateTime.parse(x['created_at']) }
143
+ issues_or_pulls.sort_by { |x| DateTime.parse(x["created_at"]) }
164
144
  end
165
145
 
166
146
  # Given an Array of issues or pulls, return the oldest.
@@ -181,7 +161,7 @@ class HowIs
181
161
 
182
162
  # Given an issue or PR, returns the date it was created.
183
163
  def date_for(issue_or_pull)
184
- DateTime.parse(issue_or_pull['created_at'])
164
+ DateTime.parse(issue_or_pull["created_at"])
185
165
  end
186
166
 
187
167
  private
@@ -192,7 +172,7 @@ class HowIs
192
172
  labels.map { |label, num_issues|
193
173
  label_link = "https://github.com/#{repository}/issues?q=" + CGI.escape("is:open is:issue label:\"#{label}\"")
194
174
 
195
- [label, {'link' => label_link, 'total' => num_issues}]
175
+ [label, {"link" => label_link, "total" => num_issues}]
196
176
  }.to_h
197
177
  end
198
178
 
@@ -206,11 +186,37 @@ class HowIs
206
186
 
207
187
  ret = {}
208
188
 
209
- ret['html_url'] = iop['html_url']
210
- ret['number'] = iop['number']
211
- ret['date'] = date_for(iop)
189
+ ret["html_url"] = iop["html_url"]
190
+ ret["number"] = iop["number"]
191
+ ret["date"] = date_for(iop)
212
192
 
213
193
  ret
214
194
  end
195
+
196
+ SECONDS_IN_A_YEAR = 31_556_926
197
+ SECONDS_IN_A_MONTH = 2_629_743
198
+ SECONDS_IN_A_WEEK = 604_800
199
+ SECONDS_IN_A_DAY = 86_400
200
+
201
+ # Calculates a list of pairs of value and period label.
202
+ #
203
+ # @param age_in_seconds [Float]
204
+ #
205
+ # @return [Array<Array>] The input age_in_seconds expressed as different
206
+ # units, as pairs of value and unit name.
207
+ def period_pairs_for(age_in_seconds)
208
+ years_remainder = age_in_seconds % SECONDS_IN_A_YEAR
209
+
210
+ months_remainder = years_remainder % SECONDS_IN_A_MONTH
211
+
212
+ weeks_remainder = months_remainder % SECONDS_IN_A_WEEK
213
+
214
+ [
215
+ [age_in_seconds / SECONDS_IN_A_YEAR, "year"],
216
+ [years_remainder / SECONDS_IN_A_MONTH, "month"],
217
+ [months_remainder / SECONDS_IN_A_WEEK, "week"],
218
+ [weeks_remainder / SECONDS_IN_A_DAY, "day"],
219
+ ]
220
+ end
215
221
  end
216
222
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HowIs
4
+ # Investigates who is a new committer since given date
5
+ #
6
+ # # /repos/:owner/:repo/commits?since=<start date for the report>
7
+ class Contributions
8
+ # @param github [Github] configured github client
9
+ # @param since_date [String] A value which fits Repos.Commits "since" and
10
+ # "until" fields. This supports many formats, for
11
+ # example a timestamp in ISO 8601 format:
12
+ # YYYY-MM-DDTHH:MM:SSZ.
13
+ # @param user [String] GitHub user of repository
14
+ # @param repo [String] GitHub repository name
15
+ def initialize(github:, since_date:, user:, repo:)
16
+ @github = github
17
+ @since_date = since_date
18
+ @user = user
19
+ @repo = repo
20
+ end
21
+
22
+ # Returns a list of contributors that have zero commits before the @since_date.
23
+ #
24
+ # @return [Hash{String => Hash] Committers keyed by GitHub login name
25
+ def new_contributors
26
+ # author: GitHub login, name or email by which to filter by commit author.
27
+ all_contributors.select do |email, _committer|
28
+ @github.repos.commits.list(user: @user,
29
+ repo: @repo,
30
+ until: @since_date,
31
+ author: email).count.zero?
32
+ end
33
+ end
34
+
35
+ # @return [Hash{String => Hash}] Author information keyed by author's email
36
+ def all_contributors
37
+ commits.map { |api_response|
38
+ [api_response.commit.author.email, api_response.commit.author.to_h]
39
+ }.to_h
40
+ end
41
+
42
+ def commits
43
+ @github.repos.commits.list(user: @user, repo: @repo, since: @since_date)
44
+ end
45
+ end
46
+ end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'contracts'
4
- require 'github_api'
5
- require 'how_is/pulse'
3
+ require "contracts"
4
+ require "github_api"
5
+ require "how_is/pulse"
6
6
 
7
- ##
8
- # Fetches data from GitHub.
9
7
  class HowIs
8
+ ##
9
+ # Fetches data from GitHub.
10
10
  class Fetcher
11
11
  include Contracts::Core
12
12
 
@@ -15,7 +15,7 @@ class HowIs
15
15
  #
16
16
  # Implemented as a class instead of passing around a Hash so that it can
17
17
  # be more easily referenced by Contracts.
18
- class Results < Struct.new(:repository, :issues, :pulls, :pulse)
18
+ Results = Struct.new(:repository, :issues, :pulls, :pulse) do
19
19
  include Contracts::Core
20
20
 
21
21
  Contract String, C::ArrayOf[Hash], C::ArrayOf[Hash], String => nil
@@ -37,12 +37,12 @@ class HowIs
37
37
  pulse = nil)
38
38
  github ||= Github.new(auto_pagination: true)
39
39
  pulse ||= HowIs::Pulse.new(repository)
40
- user, repo = repository.split('/', 2)
40
+ user, repo = repository.split("/", 2)
41
41
 
42
42
  unless user && repo
43
- raise HowIs::CLI::OptionsError, 'To generate a report from GitHub, ' \
44
- 'provide the repository ' \
45
- 'username/project. Quitting!'
43
+ raise HowIs::CLI::OptionsError, "To generate a report from GitHub, " \
44
+ "provide the repository " \
45
+ "username/project. Quitting!"
46
46
  end
47
47
 
48
48
  issues = github.issues.list user: user, repo: repo