ruby-link-checker 0.3.0 → 0.4.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.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/CONTRIBUTING.md +0 -0
  4. data/Dangerfile +2 -0
  5. data/Gemfile +2 -1
  6. data/Gemfile.lock +202 -83
  7. data/LICENSE.md +0 -0
  8. data/README.md +73 -3
  9. data/RELEASING.md +0 -0
  10. data/Rakefile +0 -0
  11. data/benchmarks/check.rb +27 -20
  12. data/benchmarks/data/opensearch.org/links.txt +0 -0
  13. data/benchmarks/data/opensearch.org/small.txt +0 -0
  14. data/coverage/assets/{0.13.1 → 0.13.2}/DataTables-1.10.20/images/sort_asc.png +0 -0
  15. data/coverage/assets/{0.13.1 → 0.13.2}/DataTables-1.10.20/images/sort_asc_disabled.png +0 -0
  16. data/coverage/assets/{0.13.1 → 0.13.2}/DataTables-1.10.20/images/sort_both.png +0 -0
  17. data/coverage/assets/{0.13.1 → 0.13.2}/DataTables-1.10.20/images/sort_desc.png +0 -0
  18. data/coverage/assets/{0.13.1 → 0.13.2}/DataTables-1.10.20/images/sort_desc_disabled.png +0 -0
  19. data/coverage/assets/{0.13.1 → 0.13.2}/application.css +0 -0
  20. data/coverage/assets/{0.13.1 → 0.13.2}/application.js +0 -0
  21. data/coverage/assets/{0.13.1 → 0.13.2}/colorbox/border.png +0 -0
  22. data/coverage/assets/{0.13.1 → 0.13.2}/colorbox/controls.png +0 -0
  23. data/coverage/assets/{0.13.1 → 0.13.2}/colorbox/loading.gif +0 -0
  24. data/coverage/assets/{0.13.1 → 0.13.2}/colorbox/loading_background.png +0 -0
  25. data/coverage/assets/{0.13.1 → 0.13.2}/favicon_green.png +0 -0
  26. data/coverage/assets/{0.13.1 → 0.13.2}/favicon_red.png +0 -0
  27. data/coverage/assets/{0.13.1 → 0.13.2}/favicon_yellow.png +0 -0
  28. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  29. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  30. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  31. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  32. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  33. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  34. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  35. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  36. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-icons_222222_256x240.png +0 -0
  37. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-icons_2e83ff_256x240.png +0 -0
  38. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-icons_454545_256x240.png +0 -0
  39. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-icons_888888_256x240.png +0 -0
  40. data/coverage/assets/{0.13.1 → 0.13.2}/images/ui-icons_cd0a0a_256x240.png +0 -0
  41. data/coverage/assets/{0.13.1 → 0.13.2}/loading.gif +0 -0
  42. data/coverage/assets/{0.13.1 → 0.13.2}/magnify.png +0 -0
  43. data/coverage/index.html +2857 -7125
  44. data/lib/ruby-link-checker/async/http/checker.rb +92 -0
  45. data/lib/ruby-link-checker/async/http/config.rb +35 -0
  46. data/lib/ruby-link-checker/async/http/result.rb +81 -0
  47. data/lib/ruby-link-checker/async/http.rb +3 -0
  48. data/lib/ruby-link-checker/callbacks.rb +2 -2
  49. data/lib/ruby-link-checker/checker.rb +0 -0
  50. data/lib/ruby-link-checker/config.rb +2 -0
  51. data/lib/ruby-link-checker/errors/base_error.rb +0 -0
  52. data/lib/ruby-link-checker/errors/redirect_loop_error.rb +0 -0
  53. data/lib/ruby-link-checker/errors.rb +0 -0
  54. data/lib/ruby-link-checker/logger.rb +0 -0
  55. data/lib/ruby-link-checker/net/http/checker.rb +2 -0
  56. data/lib/ruby-link-checker/net/http/config.rb +0 -0
  57. data/lib/ruby-link-checker/net/http/result.rb +0 -0
  58. data/lib/ruby-link-checker/net/http.rb +0 -0
  59. data/lib/ruby-link-checker/result.rb +0 -0
  60. data/lib/ruby-link-checker/task.rb +0 -0
  61. data/lib/ruby-link-checker/tasks.rb +4 -2
  62. data/lib/ruby-link-checker/typhoeus/hydra/checker.rb +2 -1
  63. data/lib/ruby-link-checker/typhoeus/hydra/config.rb +0 -0
  64. data/lib/ruby-link-checker/typhoeus/hydra/result.rb +0 -0
  65. data/lib/ruby-link-checker/typhoeus/hydra.rb +0 -0
  66. data/lib/ruby-link-checker/version.rb +1 -1
  67. data/lib/ruby-link-checker.rb +1 -0
  68. data/lib/ruby_link_checker.rb +0 -0
  69. data/ruby-link-checker.gemspec +2 -1
  70. data/spec/fixtures/200.yml +0 -0
  71. data/spec/fixtures/301_200.yml +0 -0
  72. data/spec/fixtures/301_301.yml +0 -0
  73. data/spec/fixtures/301_400_301_200.yml +0 -0
  74. data/spec/fixtures/301_403.yml +0 -0
  75. data/spec/fixtures/308_429.yml +0 -0
  76. data/spec/fixtures/404.yml +0 -0
  77. data/spec/fixtures/404_200.yml +0 -0
  78. data/spec/fixtures/404_404.yml +0 -0
  79. data/spec/fixtures/429_200.yml +0 -0
  80. data/spec/fixtures/429_429_200.yml +0 -0
  81. data/spec/ruby-link-checker/async/http/checker_spec.rb +99 -0
  82. data/spec/ruby-link-checker/callbacks_spec.rb +33 -0
  83. data/spec/ruby-link-checker/checker_spec.rb +0 -0
  84. data/spec/ruby-link-checker/config_spec.rb +0 -0
  85. data/spec/ruby-link-checker/errors/redirect_loop_error_spec.rb +18 -0
  86. data/spec/ruby-link-checker/net/http/checker_spec.rb +17 -0
  87. data/spec/ruby-link-checker/result_error_spec.rb +17 -0
  88. data/spec/ruby-link-checker/result_spec.rb +41 -0
  89. data/spec/ruby-link-checker/task_spec.rb +20 -0
  90. data/spec/ruby-link-checker/tasks_spec.rb +47 -0
  91. data/spec/ruby-link-checker/typhoeus/hydra/checker_spec.rb +28 -2
  92. data/spec/ruby-link-checker/version_spec.rb +0 -0
  93. data/spec/spec_helper.rb +3 -1
  94. data/spec/support/config.rb +0 -0
  95. data/spec/support/link_checker.rb +24 -0
  96. data/spec/support/vcr.rb +0 -0
  97. data/spec/support/with_result.rb +0 -0
  98. data/spec/support/with_url.rb +0 -0
  99. metadata +57 -37
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9ea6677f60dadfb539ccb221a11e2b849c3952c9fe16e0a1a2ea1efa21d78a5
4
- data.tar.gz: 87cd0d2879550d892a2da118e2748ce793327cf7692954c5844ab5d3d9699555
3
+ metadata.gz: 897f3eea2de5db8a96be6cb0479ffcac9cfb626266dddf48c3b76faa7cdca60b
4
+ data.tar.gz: 06a8c2535dd9d97e6c46d5a8ccf34eee5b17257a6fff31b31d9e9318f501c945
5
5
  SHA512:
6
- metadata.gz: e0e4d45deef7d00ec921c5f10a3b96c876ea79347a14d27b202acbcd954b50e5bef5f82afa4597fba3d79ccedb912d90d7403d014b742d313e0abcfac4ef1e37
7
- data.tar.gz: 0b0fd601a082a23f951ba7616336b12e0ddfe6f970bdb5897c21c5c36fa08853e2afa7d09e9698dba3e621702db9784f915a8dfe0e85a6f2c408f17ee698146a
6
+ metadata.gz: b642d6859e0a5133fc1f29a35e1be83159e08df750d809c7c847920861da618edd19519425e6dac60914610b5f9584929f8bfe78b528af049c456eaae9e76048
7
+ data.tar.gz: 424910c0aa3167ffcad39e87c143a2fef869db4c8e7050d3b056aabc47bbb34b9ef6651f848a277ae638858f4659f7887e5481e7e5b4490e6d26da298d43f440
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ### 0.4.0 (2026/8/17)
2
+
3
+ * [#13](https://github.com/dblock/ruby-link-checker/pull/13): Fix `SystemStackError` caused by infinite recursion in `_handle_result` - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot).
4
+ * [#14](https://github.com/dblock/ruby-link-checker/pull/14): Migrate Danger to use danger-pr-comment workflow - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot).
5
+ * [#14](https://github.com/dblock/ruby-link-checker/pull/14): Removed Code Climate - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot).
6
+ * [#15](https://github.com/dblock/ruby-link-checker/pull/15): Added Codecov - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot).
7
+ * [#18](https://github.com/dblock/ruby-link-checker/pull/18): Added Ruby 4.0 to the CI test matrix - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot).
8
+ * [#19](https://github.com/dblock/ruby-link-checker/pull/19): Added `LinkChecker::Async::HTTP`, a link checker based on [async-http](https://github.com/socketry/async-http) - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot).
9
+ * [#19](https://github.com/dblock/ruby-link-checker/pull/19): Dropped support for Ruby < 3.3 - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot).
10
+ * [#20](https://github.com/dblock/ruby-link-checker/pull/20): Added support for custom headers - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot).
11
+ * [#21](https://github.com/dblock/ruby-link-checker/pull/21): Improved test coverage to 100% and fixed Danger dry_run failure by unpinning `danger-changelog` - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/Copilot).
12
+
1
13
  ### 0.3.0 (2025-07-05)
2
14
 
3
15
  * [#10](https://github.com/dblock/ruby-link-checker/pull/10): Add a space after `:` to help rendering in GHA - [@dblock](https://github.com/dblock).
data/CONTRIBUTING.md CHANGED
File without changes
data/Dangerfile CHANGED
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ danger.import_dangerfile(gem: 'danger-pr-comment')
4
+
3
5
  changelog.check!
4
6
  toc.check!
data/Gemfile CHANGED
@@ -8,7 +8,8 @@ gem 'rake'
8
8
 
9
9
  group :development, :test do
10
10
  gem 'danger'
11
- gem 'danger-changelog', '0.6.1'
11
+ gem 'danger-changelog', '0.8.0'
12
+ gem 'danger-pr-comment'
12
13
  gem 'danger-toc', '0.2.0'
13
14
  gem 'rspec', '~> 3.0'
14
15
  gem 'rubocop', '~> 1.0'
data/Gemfile.lock CHANGED
@@ -1,44 +1,62 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-link-checker (0.3.0)
4
+ ruby-link-checker (0.4.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
- activesupport (8.0.2)
9
+ activesupport (8.1.3.1)
10
10
  base64
11
- benchmark (>= 0.3)
12
11
  bigdecimal
13
12
  concurrent-ruby (~> 1.0, >= 1.3.1)
14
13
  connection_pool (>= 2.2.5)
15
14
  drb
16
15
  i18n (>= 1.6, < 2)
16
+ json
17
17
  logger (>= 1.4.2)
18
18
  minitest (>= 5.1)
19
19
  securerandom (>= 0.3)
20
20
  tzinfo (~> 2.0, >= 2.0.5)
21
21
  uri (>= 0.13.1)
22
- addressable (2.8.7)
23
- public_suffix (>= 2.0.2, < 7.0)
22
+ addressable (2.9.0)
23
+ public_suffix (>= 2.0.2, < 8.0)
24
24
  ast (2.4.3)
25
+ async (2.44.1)
26
+ console (~> 1.29)
27
+ fiber-annotation
28
+ io-event (~> 1.11)
29
+ async-http (0.99.0)
30
+ async (>= 2.35.1)
31
+ async-pool (~> 0.11)
32
+ io-endpoint (~> 0.14)
33
+ io-stream (~> 0.14)
34
+ protocol-http (~> 0.66)
35
+ protocol-http1 (~> 0.39)
36
+ protocol-http2 (~> 0.26)
37
+ protocol-url (~> 0.2)
38
+ async-pool (0.11.2)
39
+ async (>= 2.0)
25
40
  base64 (0.3.0)
26
- benchmark (0.4.1)
27
- bigdecimal (3.2.2)
41
+ bigdecimal (4.1.2)
28
42
  claide (1.1.0)
29
43
  claide-plugins (0.9.2)
30
44
  cork
31
45
  nap
32
46
  open4 (~> 1.3)
33
47
  colored2 (3.1.2)
34
- concurrent-ruby (1.3.5)
35
- connection_pool (2.5.3)
48
+ concurrent-ruby (1.3.8)
49
+ connection_pool (3.0.2)
50
+ console (1.37.0)
51
+ fiber-annotation
52
+ fiber-local (~> 1.1)
53
+ json
36
54
  cork (0.3.0)
37
55
  colored2 (~> 3.1)
38
- crack (1.0.0)
56
+ crack (1.0.1)
39
57
  bigdecimal
40
58
  rexml
41
- danger (9.5.3)
59
+ danger (9.6.1)
42
60
  base64 (~> 0.2)
43
61
  claide (~> 1.0)
44
62
  claide-plugins (>= 0.9.2)
@@ -46,16 +64,18 @@ GEM
46
64
  cork (~> 0.1)
47
65
  faraday (>= 0.9.0, < 3.0)
48
66
  faraday-http-cache (~> 2.0)
49
- git (>= 1.13, < 3.0)
67
+ git (>= 1.13)
50
68
  kramdown (>= 2.5.1, < 3.0)
51
69
  kramdown-parser-gfm (~> 1.0)
52
70
  octokit (>= 4.0)
53
71
  pstore (~> 0.1)
54
72
  terminal-table (>= 1, < 5)
55
- danger-changelog (0.6.1)
73
+ danger-changelog (0.8.0)
56
74
  danger-plugin-api (~> 1.0)
57
75
  danger-plugin-api (1.0.0)
58
76
  danger (> 2.0)
77
+ danger-pr-comment (0.1.0)
78
+ danger (~> 9)
59
79
  danger-toc (0.2.0)
60
80
  activesupport
61
81
  danger-plugin-api (~> 1.0)
@@ -63,79 +83,90 @@ GEM
63
83
  diff-lcs (1.6.2)
64
84
  docile (1.4.1)
65
85
  drb (2.2.3)
66
- ethon (0.16.0)
86
+ ethon (0.15.0)
67
87
  ffi (>= 1.15.0)
68
- faraday (2.13.2)
88
+ faraday (2.14.3)
69
89
  faraday-net_http (>= 2.0, < 3.5)
70
90
  json
71
91
  logger
72
- faraday-http-cache (2.5.1)
92
+ faraday-http-cache (2.7.0)
73
93
  faraday (>= 0.8)
74
- faraday-net_http (3.4.1)
75
- net-http (>= 0.5.0)
76
- ffi (1.17.2)
77
- ffi (1.17.2-aarch64-linux-gnu)
78
- ffi (1.17.2-aarch64-linux-musl)
79
- ffi (1.17.2-arm-linux-gnu)
80
- ffi (1.17.2-arm-linux-musl)
81
- ffi (1.17.2-arm64-darwin)
82
- ffi (1.17.2-x86-linux-gnu)
83
- ffi (1.17.2-x86-linux-musl)
84
- ffi (1.17.2-x86_64-darwin)
85
- ffi (1.17.2-x86_64-linux-gnu)
86
- ffi (1.17.2-x86_64-linux-musl)
87
- git (2.3.3)
94
+ faraday-net_http (3.4.4)
95
+ net-http (~> 0.5)
96
+ ffi (1.17.3-aarch64-linux-gnu)
97
+ ffi (1.17.3-aarch64-mingw-ucrt)
98
+ fiber-annotation (0.2.0)
99
+ fiber-local (1.1.0)
100
+ fiber-storage
101
+ fiber-storage (1.0.1)
102
+ git (5.0.5)
88
103
  activesupport (>= 5.0)
89
104
  addressable (~> 2.8)
90
- process_executer (~> 1.1)
91
- rchardet (~> 1.8)
92
- hashdiff (1.2.0)
93
- i18n (1.14.7)
105
+ process_executer (~> 4.0)
106
+ rchardet (~> 1.9)
107
+ hashdiff (1.2.1)
108
+ i18n (1.15.2)
94
109
  concurrent-ruby (~> 1.0)
95
- json (2.12.2)
96
- kramdown (2.5.1)
97
- rexml (>= 3.3.9)
110
+ io-endpoint (0.17.2)
111
+ io-event (1.19.5)
112
+ io-stream (0.14.0)
113
+ openssl (>= 3.3)
114
+ json (2.21.2)
115
+ kramdown (2.5.2)
116
+ rexml (>= 3.4.4)
98
117
  kramdown-parser-gfm (1.1.0)
99
118
  kramdown (~> 2.0)
100
119
  language_server-protocol (3.17.0.5)
101
120
  lint_roller (1.1.0)
102
121
  logger (1.7.0)
103
- minitest (5.25.5)
122
+ minitest (6.0.6)
123
+ drb (~> 2.0)
124
+ prism (~> 1.5)
104
125
  nap (1.1.0)
105
- net-http (0.6.0)
106
- uri
126
+ net-http (0.9.1)
127
+ uri (>= 0.11.1)
107
128
  octokit (10.0.0)
108
129
  faraday (>= 1, < 3)
109
130
  sawyer (~> 0.9)
110
131
  open4 (1.3.4)
132
+ openssl (4.0.2)
111
133
  parallel (1.27.0)
112
- parser (3.3.8.0)
134
+ parser (3.3.10.1)
113
135
  ast (~> 2.4.1)
114
136
  racc
115
- prism (1.4.0)
116
- process_executer (1.3.0)
117
- pstore (0.2.0)
118
- public_suffix (6.0.2)
137
+ prism (1.9.0)
138
+ process_executer (4.0.4)
139
+ track_open_instances (~> 0.1)
140
+ protocol-hpack (1.5.1)
141
+ protocol-http (0.71.0)
142
+ protocol-http1 (0.40.2)
143
+ protocol-http (~> 0.68)
144
+ protocol-http2 (0.26.2)
145
+ protocol-hpack (~> 1.4)
146
+ protocol-http (~> 0.62)
147
+ protocol-url (0.18.0)
148
+ pstore (0.2.1)
149
+ public_suffix (7.0.5)
119
150
  racc (1.8.1)
120
151
  rainbow (3.1.1)
121
- rake (13.3.0)
122
- rchardet (1.9.0)
123
- regexp_parser (2.10.0)
124
- rexml (3.4.1)
125
- rspec (3.13.1)
152
+ rake (13.3.1)
153
+ rchardet (1.10.2)
154
+ regexp_parser (2.11.3)
155
+ rexml (3.4.4)
156
+ rspec (3.13.2)
126
157
  rspec-core (~> 3.13.0)
127
158
  rspec-expectations (~> 3.13.0)
128
159
  rspec-mocks (~> 3.13.0)
129
- rspec-core (3.13.5)
160
+ rspec-core (3.13.6)
130
161
  rspec-support (~> 3.13.0)
131
162
  rspec-expectations (3.13.5)
132
163
  diff-lcs (>= 1.2.0, < 2.0)
133
164
  rspec-support (~> 3.13.0)
134
- rspec-mocks (3.13.5)
165
+ rspec-mocks (3.13.7)
135
166
  diff-lcs (>= 1.2.0, < 2.0)
136
167
  rspec-support (~> 3.13.0)
137
- rspec-support (3.13.4)
138
- rubocop (1.77.0)
168
+ rspec-support (3.13.7)
169
+ rubocop (1.84.0)
139
170
  json (~> 2.3)
140
171
  language_server-protocol (~> 3.17.0.2)
141
172
  lint_roller (~> 1.1.0)
@@ -143,20 +174,20 @@ GEM
143
174
  parser (>= 3.3.0.2)
144
175
  rainbow (>= 2.2.2, < 4.0)
145
176
  regexp_parser (>= 2.9.3, < 3.0)
146
- rubocop-ast (>= 1.45.1, < 2.0)
177
+ rubocop-ast (>= 1.49.0, < 2.0)
147
178
  ruby-progressbar (~> 1.7)
148
179
  unicode-display_width (>= 2.4.0, < 4.0)
149
- rubocop-ast (1.45.1)
180
+ rubocop-ast (1.49.0)
150
181
  parser (>= 3.3.7.2)
151
- prism (~> 1.4)
182
+ prism (~> 1.7)
152
183
  rubocop-rake (0.7.1)
153
184
  lint_roller (~> 1.1)
154
185
  rubocop (>= 1.72.1)
155
- rubocop-rspec (3.6.0)
186
+ rubocop-rspec (3.9.0)
156
187
  lint_roller (~> 1.1)
157
- rubocop (~> 1.72, >= 1.72.1)
188
+ rubocop (~> 1.81)
158
189
  ruby-progressbar (1.13.0)
159
- sawyer (0.9.2)
190
+ sawyer (0.9.3)
160
191
  addressable (>= 2.3.5)
161
192
  faraday (>= 0.17.3, < 3)
162
193
  securerandom (0.4.1)
@@ -164,41 +195,34 @@ GEM
164
195
  docile (~> 1.1)
165
196
  simplecov-html (~> 0.11)
166
197
  simplecov_json_formatter (~> 0.1)
167
- simplecov-html (0.13.1)
198
+ simplecov-html (0.13.2)
168
199
  simplecov_json_formatter (0.1.4)
169
200
  terminal-table (4.0.0)
170
201
  unicode-display_width (>= 1.1.1, < 4)
171
- typhoeus (1.4.1)
172
- ethon (>= 0.9.0)
202
+ track_open_instances (0.1.15)
203
+ typhoeus (1.5.0)
204
+ ethon (>= 0.9.0, < 0.16.0)
173
205
  tzinfo (2.0.6)
174
206
  concurrent-ruby (~> 1.0)
175
- unicode-display_width (3.1.4)
176
- unicode-emoji (~> 4.0, >= 4.0.4)
177
- unicode-emoji (4.0.4)
178
- uri (1.0.3)
179
- vcr (6.3.1)
180
- base64
181
- webmock (3.25.1)
207
+ unicode-display_width (3.2.0)
208
+ unicode-emoji (~> 4.1)
209
+ unicode-emoji (4.2.0)
210
+ uri (1.1.1)
211
+ vcr (6.4.0)
212
+ webmock (3.26.1)
182
213
  addressable (>= 2.8.0)
183
214
  crack (>= 0.3.2)
184
215
  hashdiff (>= 0.4.0, < 2.0.0)
185
216
 
186
217
  PLATFORMS
187
- aarch64-linux-gnu
188
- aarch64-linux-musl
189
- arm-linux-gnu
190
- arm-linux-musl
191
- arm64-darwin
192
- ruby
193
- x86-linux-gnu
194
- x86-linux-musl
195
- x86_64-darwin
196
- x86_64-linux-gnu
197
- x86_64-linux-musl
218
+ aarch64-linux
219
+ aarch64-mingw-ucrt
198
220
 
199
221
  DEPENDENCIES
222
+ async-http
200
223
  danger
201
- danger-changelog (= 0.6.1)
224
+ danger-changelog (= 0.8.0)
225
+ danger-pr-comment
202
226
  danger-toc (= 0.2.0)
203
227
  rake
204
228
  rspec (~> 3.0)
@@ -211,5 +235,100 @@ DEPENDENCIES
211
235
  vcr
212
236
  webmock
213
237
 
238
+ CHECKSUMS
239
+ activesupport (8.1.3.1) sha256=85458765f25ea48b9019c46b6bb3fa5683197bf4280d9f06710a6e8d7a831376
240
+ addressable (2.9.0) sha256=7fdf6ac3660f7f4e867a0838be3f6cf722ace541dd97767fa42bc6cfa980c7af
241
+ ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
242
+ async (2.44.1) sha256=079bce0d019fb27cc58ec110fd9b9af4991d97b801d1c6cc6def1d1954dcf9b2
243
+ async-http (0.99.0) sha256=665eba5e530b05a9682c78b3aa5a51e97dd67b8b25b71ba76530b60cf6c26a11
244
+ async-pool (0.11.2) sha256=0a43a17b02b04d9c451b7d12fafa9a50e55dc6dd00d4369aca00433f16a7e3ed
245
+ base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
246
+ bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
247
+ claide (1.1.0) sha256=6d3c5c089dde904d96aa30e73306d0d4bd444b1accb9b3125ce14a3c0183f82e
248
+ claide-plugins (0.9.2) sha256=c7ea78bc067ab23bce8515497cdcdcb8f01c86dadfbe13c44644e382922c1c2e
249
+ colored2 (3.1.2) sha256=b13c2bd7eeae2cf7356a62501d398e72fde78780bd26aec6a979578293c28b4a
250
+ concurrent-ruby (1.3.8) sha256=b2f1be836e968ccc78ccfce277ea79c72a88633f22306782c16ff23fb415d1e1
251
+ connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
252
+ console (1.37.0) sha256=8093b286c2595a063849c098594fee5155ecc7967d36f3aa8cbe7569c8f3efd7
253
+ cork (0.3.0) sha256=a0a0ac50e262f8514d1abe0a14e95e71c98b24e3378690e5d044daf0013ad4bc
254
+ crack (1.0.1) sha256=ff4a10390cd31d66440b7524eb1841874db86201d5b70032028553130b6d4c7e
255
+ danger (9.6.1) sha256=ca1b870fd8e9f27add22c5649e976efcfb3c76a57f5c7739bb3f1a72ce0506b7
256
+ danger-changelog (0.8.0) sha256=c2ba086861ee2b31990cce8d13d0f967ec5ea43c8cb438d61d147b539b56b7cd
257
+ danger-plugin-api (1.0.0) sha256=a0f3f4f2c19fbdfb41db6015fe8ed5eeb2588dc71f2f78d580294c2b10f83bd3
258
+ danger-pr-comment (0.1.0) sha256=82936d5cecaabd24de50273c3048b89afa5176cfaf5971d863fafbc7a7d923f3
259
+ danger-toc (0.2.0) sha256=6d4d767224a0f6048f4aa5679a3627fb38cc1902fdc407c43eeac23765d2c0a9
260
+ diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
261
+ docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e
262
+ drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
263
+ ethon (0.15.0) sha256=0809805a035bc10f54162ca99f15ded49e428e0488bcfe1c08c821e18261a74d
264
+ faraday (2.14.3) sha256=1882247e6766615c8220b4392bf1d27f6ebb63d8e28267587cef1fb0bf37f278
265
+ faraday-http-cache (2.7.0) sha256=cd7ac4bbe6c08592ea7af6655f98b2f76c4db0bad31bf40340df5aad719f0d89
266
+ faraday-net_http (3.4.4) sha256=0e78af151747ed1b00f33e25973b4bc220d7f16c00c39676817c8b12331eb588
267
+ ffi (1.17.3-aarch64-linux-gnu) sha256=28ad573df26560f0aedd8a90c3371279a0b2bd0b4e834b16a2baa10bd7a97068
268
+ ffi (1.17.3-aarch64-mingw-ucrt) sha256=3a265ea6eb15284287bf3ea2bd80d2550c7cab8ba485b41f9ce00e2d84a10b58
269
+ fiber-annotation (0.2.0) sha256=7abfadf1d119f508867d4103bf231c0354d019cc39a5738945dec2edadaf6c03
270
+ fiber-local (1.1.0) sha256=c885f94f210fb9b05737de65d511136ea602e00c5105953748aa0f8793489f06
271
+ fiber-storage (1.0.1) sha256=f48e5b6d8b0be96dac486332b55cee82240057065dc761c1ea692b2e719240e1
272
+ git (5.0.5) sha256=aa84f7b0d4955e885dc55fb3b9f028b3532d40ec5111109bf2cc3b17d5a91373
273
+ hashdiff (1.2.1) sha256=9c079dbc513dfc8833ab59c0c2d8f230fa28499cc5efb4b8dd276cf931457cd1
274
+ i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5
275
+ io-endpoint (0.17.2) sha256=3feaf766c116b35839c11fac68b6aaadc47887bb488902a57bf8e1d288fb3338
276
+ io-event (1.19.5) sha256=b168a9b7c5a0e894f2047f82f4bf831f59edd067843005e930a62f375738bad2
277
+ io-stream (0.14.0) sha256=07d9b13ea2066ccbbc761fff8d69ad5a31e47561d31e02cc271f3ed9c1a8f1cd
278
+ json (2.21.2) sha256=1f1d3b7cf2b3ba1a69beca0bb6db13d5438b80bff3cd54cdaaa620b9b07c1c6a
279
+ kramdown (2.5.2) sha256=1ba542204c66b6f9111ff00dcc26075b95b220b07f2905d8261740c82f7f02fa
280
+ kramdown-parser-gfm (1.1.0) sha256=fb39745516427d2988543bf01fc4cf0ab1149476382393e0e9c48592f6581729
281
+ language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
282
+ lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
283
+ logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
284
+ minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
285
+ nap (1.1.0) sha256=949691660f9d041d75be611bb2a8d2fd559c467537deac241f4097d9b5eea576
286
+ net-http (0.9.1) sha256=25ba0b67c63e89df626ed8fac771d0ad24ad151a858af2cc8e6a716ca4336996
287
+ octokit (10.0.0) sha256=82e99a539b7637b7e905e6d277bb0c1a4bed56735935cc33db6da7eae49a24e8
288
+ open4 (1.3.4) sha256=a1df037310624ecc1ea1d81264b11c83e96d0c3c1c6043108d37d396dcd0f4b1
289
+ openssl (4.0.2) sha256=1037ad2868ae58df9ad917891c0c0f9815a1172f6846d4bcdd508e4c2ee747c2
290
+ parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
291
+ parser (3.3.10.1) sha256=06f6a725d2cd91e5e7f2b7c32ba143631e1f7c8ae2fb918fc4cebec187e6a688
292
+ prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
293
+ process_executer (4.0.4) sha256=6c179bd31b876e220e7a1ed30c8f8ee7333b9b5b4b8c301474b947b707c3ba6f
294
+ protocol-hpack (1.5.1) sha256=6feca238b8078da1cd295677d6f306c6001af92d75fe0643d33e6956cbc3ad91
295
+ protocol-http (0.71.0) sha256=38577bf3df0bf0c3f7ee7e21b43fcb4bd7624e36f697dbe9c3eea344f14bd9ba
296
+ protocol-http1 (0.40.2) sha256=add1191f06f16077b2e319ec5cf38c8623a2d2a9829f88a36ebaf8ecf80748a9
297
+ protocol-http2 (0.26.2) sha256=1457cfaa31877512c349051e0094ea170b8913a62d966b82ff7cd14e4b1a3ede
298
+ protocol-url (0.18.0) sha256=b16f55983094b46d18e04b709333b260e4ab5962a32696728e33a6c396150ed6
299
+ pstore (0.2.1) sha256=03904d0f2c66579e96d1e6704cdabc0c88df7ea8ed8782d9f3569f6f6c702c1a
300
+ public_suffix (7.0.5) sha256=1a8bb08f1bbea19228d3bed6e5ed908d1cb4f7c2726d18bd9cadf60bc676f623
301
+ racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
302
+ rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
303
+ rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
304
+ rchardet (1.10.2) sha256=e041cb195f464dc10e49ab130f78c8b5956cd9a4f4f6df84e0c183b87c135f33
305
+ regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4
306
+ rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142
307
+ rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
308
+ rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
309
+ rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
310
+ rspec-mocks (3.13.7) sha256=0979034e64b1d7a838aaaddf12bf065ea4dc40ef3d4c39f01f93ae2c66c62b1c
311
+ rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
312
+ rubocop (1.84.0) sha256=88dec310153bb685a879f5a7cdb601f6287b8f0ee675d9dc63a17c7204c4190a
313
+ rubocop-ast (1.49.0) sha256=49c3676d3123a0923d333e20c6c2dbaaae2d2287b475273fddee0c61da9f71fd
314
+ rubocop-rake (0.7.1) sha256=3797f2b6810c3e9df7376c26d5f44f3475eda59eb1adc38e6f62ecf027cbae4d
315
+ rubocop-rspec (3.9.0) sha256=8fa70a3619408237d789aeecfb9beef40576acc855173e60939d63332fdb55e2
316
+ ruby-link-checker (0.4.0)
317
+ ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
318
+ sawyer (0.9.3) sha256=0d0f19298408047037638639fe62f4794483fb04320269169bd41af2bdcf5e41
319
+ securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
320
+ simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
321
+ simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246
322
+ simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
323
+ terminal-table (4.0.0) sha256=f504793203f8251b2ea7c7068333053f0beeea26093ec9962e62ea79f94301d2
324
+ track_open_instances (0.1.15) sha256=7f0e48821e6b4c881daaa40fb1583e308937c22a9c84883c150b399c3b5c3029
325
+ typhoeus (1.5.0) sha256=120b67ed1ef515e6c0e938176db880f15b0916f038e78ce2a66290f3f1de3e3b
326
+ tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
327
+ unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
328
+ unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
329
+ uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
330
+ vcr (6.4.0) sha256=077ac92cc16efc5904eb90492a18153b5e6ca5398046d8a249a7c96a9ea24ae6
331
+ webmock (3.26.1) sha256=4f696fb57c90a827c20aadb2d4f9058bbff10f7f043bd0d4c3f58791143b1cd7
332
+
214
333
  BUNDLED WITH
215
- 2.6.8
334
+ 4.0.3
data/LICENSE.md CHANGED
File without changes
data/README.md CHANGED
@@ -2,9 +2,8 @@ Fast Ruby Link Checker
2
2
  ======================
3
3
 
4
4
  [![Gem Version](http://img.shields.io/gem/v/ruby-link-checker.svg)](http://badge.fury.io/rb/ruby-link-checker)
5
- [![Build Status](https://github.com/dblock/ruby-link-checker/workflows/test/badge.svg?branch=main)](https://github.com/dblock/ruby-link-checker/actions)
6
- [![Code Climate](https://codeclimate.com/github/dblock/ruby-link-checker.svg)](https://codeclimate.com/github/dblock/ruby-link-checker)
7
- [![Test Coverage](https://api.codeclimate.com/v1/badges/164f1e23fc706b6efa63/test_coverage)](https://codeclimate.com/github/dblock/ruby-link-checker/test_coverage)
5
+ [![Build Status](https://github.com/dblock/ruby-link-checker/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/dblock/ruby-link-checker/actions/workflows/test.yml)
6
+ [![codecov](https://codecov.io/gh/dblock/ruby-link-checker/graph/badge.svg)](https://codecov.io/gh/dblock/ruby-link-checker)
8
7
 
9
8
  A fast Ruby link checker with support for multiple HTTP libraries. Does not parse documents, just checks links. Fast. Anecdotal benchmarking on a M1 mac and T1 Internet yields ~50 URLs per second with `LinkChecker::Typhoeus::Hydra`.
10
9
 
@@ -16,6 +15,7 @@ A fast Ruby link checker with support for multiple HTTP libraries. Does not pars
16
15
  - [Passing Options](#passing-options)
17
16
  - [Checkers](#checkers)
18
17
  - [LinkChecker::Typhoeus::Hydra](#linkcheckertyphoeushydra)
18
+ - [LinkChecker::Async::HTTP](#linkcheckerasynchttp)
19
19
  - [LinkChecker::Net::HTTP](#linkcheckernethttp)
20
20
  - [Options](#options)
21
21
  - [Retries](#retries)
@@ -24,8 +24,10 @@ A fast Ruby link checker with support for multiple HTTP libraries. Does not pars
24
24
  - [Methods](#methods)
25
25
  - [Logger](#logger)
26
26
  - [User-Agent](#user-agent)
27
+ - [Headers](#headers)
27
28
  - [Global Configuration](#global-configuration)
28
29
  - [Callbacks and Events](#callbacks-and-events)
30
+ - [Benchmarks](#benchmarks)
29
31
  - [Contributing](#contributing)
30
32
  - [Copyright and License](#copyright-and-license)
31
33
 
@@ -127,6 +129,49 @@ LinkChecker::Typhoeus::Hydra.configure do |config|
127
129
  end
128
130
  ```
129
131
 
132
+ #### [LinkChecker::Async::HTTP](lib/ruby-link-checker/async/http/checker.rb)
133
+
134
+ Fast, concurrent link checker that uses [async-http](https://github.com/socketry/async-http).
135
+
136
+ ```ruby
137
+ require 'async'
138
+ require 'async/http'
139
+ require 'ruby-link-checker'
140
+
141
+ # create a new instance of a checker
142
+ checker = LinkChecker::Async::HTTP::Checker.new
143
+
144
+ # log requests and response codes
145
+ checker.logger.level = Logger::INFO
146
+
147
+ links = [...] # array of URLs
148
+ links.each do |url|
149
+ checker.check url
150
+ end
151
+
152
+ # examine failures and errors as they come
153
+ checker.on :error, :failure do |result|
154
+ puts "FAIL: #{result}"
155
+ end
156
+
157
+ # runs all queued checks concurrently, will block until all requests have completed
158
+ checker.run
159
+
160
+ # examine results
161
+ checker.results.each_pair do |bucket, results|
162
+ puts "#{bucket}: #{results.size}"
163
+ end
164
+ ```
165
+
166
+ You can pass `Async::HTTP` timeout options into a new instance of a checker, or configure timeouts globally.
167
+
168
+ ```ruby
169
+ LinkChecker::Async::HTTP.configure do |config|
170
+ config.read_timeout = 5
171
+ config.open_timeout = 10
172
+ end
173
+ ```
174
+
130
175
  #### [LinkChecker::Net::HTTP](lib/ruby-link-checker/net/http/checker.rb)
131
176
 
132
177
  Slow, sequential checker.
@@ -227,6 +272,20 @@ Pass your own user-agent. Default is `Ruby Link Checker/x.y.z`.
227
272
  checker = LinkChecker::Net::HTTP::Checker.new(user_agent: 'Custom Agent/1.0')
228
273
  ```
229
274
 
275
+ #### Headers
276
+
277
+ Some sites reject or return errors (403, 404) to requests that look like bots. Pass additional headers to mimic a browser.
278
+
279
+ ```ruby
280
+ checker = LinkChecker::Net::HTTP::Checker.new(
281
+ headers: {
282
+ 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
283
+ 'Accept-Language' => 'en-US,en;q=0.5',
284
+ 'DNT' => '1'
285
+ }
286
+ )
287
+ ```
288
+
230
289
  ### Global Configuration
231
290
 
232
291
  All options can also be configured globally.
@@ -234,6 +293,7 @@ All options can also be configured globally.
234
293
  ```ruby
235
294
  LinkChecker.configure do |config|
236
295
  config.user_agent = 'Custom Agent/1.0'
296
+ config.headers = { 'DNT' => '1' }
237
297
  config.methods = ['HEAD', 'GET']
238
298
  config.logger = ::Logger.new(STDOUT)
239
299
  end
@@ -277,6 +337,16 @@ Events are called with results, which contain the following properties.
277
337
 
278
338
  See [result.rb](lib/ruby-link-checker/result.rb) for more details.
279
339
 
340
+ ## Benchmarks
341
+
342
+ See [benchmarks/check.rb](benchmarks/check.rb) for a script comparing the performance of the three checkers (`LinkChecker::Net::HTTP`, `LinkChecker::Typhoeus::Hydra`, and `LinkChecker::Async::HTTP`) against a fixed set of URLs.
343
+
344
+ ```
345
+ bundle exec ruby -Ilib benchmarks/check.rb
346
+ ```
347
+
348
+ Anecdotal results show `LinkChecker::Async::HTTP` using significantly less CPU time than `LinkChecker::Typhoeus::Hydra` (both concurrent checkers), while wall-clock time is comparable between the two and depends on timeouts and the responsiveness of the URLs being checked. `LinkChecker::Net::HTTP` checks links sequentially and is significantly slower in wall-clock time for large batches of URLs; it's commented out by default in the script.
349
+
280
350
  ## Contributing
281
351
 
282
352
  You're encouraged to contribute to ruby-link-checker. See [CONTRIBUTING](CONTRIBUTING.md) for details.
data/RELEASING.md CHANGED
File without changes
data/Rakefile CHANGED
File without changes
data/benchmarks/check.rb CHANGED
@@ -1,31 +1,38 @@
1
1
  require 'benchmark'
2
2
  require 'net/http'
3
3
  require 'typhoeus'
4
+ require 'async'
5
+ require 'async/http'
4
6
  require 'ruby-link-checker'
5
7
 
6
8
  input = File.readlines(File.join(__dir__, 'data/opensearch.org/small.txt')).map(&:strip)
7
9
 
8
- Benchmark.bm do |benchmark|
9
- # benchmark.report('LinkChecker::Net::HTTP::Checker') do
10
- # checker = LinkChecker::Net::HTTP::Checker.new
11
- # checker.logger.level = Logger::INFO
12
- # input.each do |url|
13
- # checker.check url
14
- # end
15
- # checker.results.each_pair do |bucket, results|
16
- # puts "#{bucket}: #{results.size}"
17
- # end
18
- # end
10
+ CHECKERS = [
11
+ # LinkChecker::Net::HTTP::Checker,
12
+ LinkChecker::Typhoeus::Hydra::Checker,
13
+ LinkChecker::Async::HTTP::Checker
14
+ ].freeze
19
15
 
20
- benchmark.report('LinkChecker::Typhoeus::Hydra::Checker') do
21
- checker = LinkChecker::Typhoeus::Hydra::Checker.new
22
- checker.logger.level = Logger::INFO
23
- input.each do |url|
24
- checker.check url
25
- end
26
- checker.run
27
- checker.results.each_pair do |bucket, results|
28
- puts "#{bucket}: #{results.size}"
16
+ Benchmark.bm(40) do |benchmark|
17
+ CHECKERS.each do |checker_klass|
18
+ benchmark.report(checker_klass.name) do
19
+ checker = checker_klass.new
20
+ checker.logger.level = Logger::INFO
21
+ case checker
22
+ when LinkChecker::Typhoeus::Hydra::Checker
23
+ checker.timeout = 5 # 1/12th of the default 60s
24
+ checker.connecttimeout = 1 # 1/10th of the default 10s
25
+ else
26
+ checker.read_timeout = 5 # 1/12th of the default 60s
27
+ checker.open_timeout = 5 # 1/12th of the default 60s
28
+ end
29
+ input.each do |url|
30
+ checker.check url
31
+ end
32
+ checker.run if checker.respond_to?(:run)
33
+ checker.results.each_pair do |bucket, results|
34
+ puts "#{bucket}: #{results.size}"
35
+ end
29
36
  end
30
37
  end
31
38
  end
File without changes
File without changes