quick_and_ruby 0.7.0 → 0.8.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
  SHA256:
3
- metadata.gz: 7ca92f547a72562016dbe6ae7c6565066c2b4677133db05202de86d5471c228b
4
- data.tar.gz: 9f60ad5846b8102a14b5a9de65b9a8e5db4bc71aaba14280196ec3739d83cb41
3
+ metadata.gz: 2be4d68167ffdc0814b0a5bb3dfada60271de21a922ef4c7b927907c7beda8db
4
+ data.tar.gz: ea517d525d665fe46fffcee29b5b77c19fdc30d97ab74b5a2518fb08fc430fa2
5
5
  SHA512:
6
- metadata.gz: 2d093d56fb8ccb86f8f6a9b37e2caf034a89742d8aae6cadaa7fc200c24f1ace18cd8fbee4e536f94e39364bb551335be14e6818892b671990a3024f49968680
7
- data.tar.gz: 60884d29f116d6adf7f41d59795d4a33ff6153fc089b4365ae57d6f1f4f3bbcb87f14d0aef95a70eb6d6b95121bb06e978aaadcace76e20e76a906cb3bd2a48d
6
+ metadata.gz: f050a85a80ce18c11257021c298c9b11af23694c06dd1ae27bd0018de33006665ac1637c9555054a275d5389afd54c04ff1195c419a77a2d28ae124409312360
7
+ data.tar.gz: d28612a9521ba0825001eb8b5065fd366839211b91b7b69eb505d5aed074100b270cabcea3d3f9f0445bccf151c7f53390e2175806d8aeec13a290261138ef2c
data/.rubocop.yml CHANGED
@@ -6,7 +6,7 @@ plugins:
6
6
 
7
7
  AllCops:
8
8
  NewCops: enable
9
- TargetRubyVersion: 3.1
9
+ TargetRubyVersion: 3.2
10
10
 
11
11
  Gemspec/DevelopmentDependencies:
12
12
  Enabled: false
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env/ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'optparse'
5
+ require 'quick_and_ruby/s3'
6
+
7
+ options = {
8
+ path: '/',
9
+ nested: false
10
+ }
11
+ option_parser = OptionParser.new do |opt|
12
+ opt.banner = 'Usage: s3_web_indexer [options]'
13
+
14
+ opt.on('-b', '--bucket BUCKET', 'S3 bucket name') { |v| options[:bucket] = v }
15
+ opt.on('-u', '--url URL', 'S3 endpoint URL') { |v| options[:endpoint_url] = v }
16
+ opt.on('-a', '--access-key KEY', 'S3 access key') { |v| options[:access_key] = v }
17
+ opt.on('-s', '--secret-key KEY', 'S3 secret access key') { |v| options[:secret_key] = v }
18
+ opt.on('-N', '--nested', 'All nested objects') { |_v| options[:nested] = true }
19
+ end
20
+
21
+ argv = ARGV.clone
22
+ option_parser.parse!(argv)
23
+
24
+ abort('Missing required arguments') unless options.values_at(
25
+ :bucket, :endpoint_url, :access_key, :secret_key
26
+ ).all?
27
+
28
+ exit QuickAndRuby::S3::WebIndexer.new(**options).index(*argv, nested: options[:nested])
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module QuickAndRuby
6
+ module S3
7
+ class WebIndexRenderer
8
+ DEFAULT_TEMPLATE = <<~HTML
9
+ <!DOCTYPE html>
10
+ <html>
11
+ <head>
12
+ <title><%= path %></title>
13
+ <style>
14
+ body { font-family: Arial, sans-serif; margin: 20px; }
15
+ h1 { color: #333; }
16
+ table { border-collapse: collapse; width: 100%; margin-top: 20px; }
17
+ th, td { padding: 8px 12px; text-align: left; border-bottom: 1px solid #ddd; }
18
+ th { background-color: #f4f4f4; font-weight: bold; }
19
+ tr:hover { background-color: #f9f9f9; }
20
+ a { color: #0066cc; text-decoration: none; }
21
+ a:hover { text-decoration: underline; }
22
+ .size { font-family: monospace; }
23
+ .date { color: #666; }
24
+ .dir { font-weight: bold; color: #228822; }
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <h1><%= path %></h1>
29
+
30
+ <% unless path == '/' %>
31
+ <p><a class="dir" href="../index.html">../</a></p>
32
+ <% end %>
33
+
34
+ <% if files.empty? %>
35
+ <p>No files found.</p>
36
+ <% else %>
37
+ <table>
38
+ <tr>
39
+ <th>Filename</th>
40
+ <th>Last Modified</th>
41
+ <th>Size</th>
42
+ </tr>
43
+ <% files.each do |file| %>
44
+ <tr>
45
+ <% if file[:is_directory] %>
46
+ <td class="dir"><a href="<%= file[:filename_relative_path] %>index.html"><%= file[:filename] %></a></td>
47
+ <td class="date"></td>
48
+ <td class="size"></td>
49
+ <% else %>
50
+ <td><a href="<%= file[:filename_relative_path] %>"><%= file[:filename] %></a></td>
51
+ <td class="date"><%= format_date(file[:last_modified]) %></td>
52
+ <td class="size"><%= format_size(file[:size]) %></td>
53
+ <% end %>
54
+ </tr>
55
+ <% end %>
56
+ </table>
57
+ <p><%= files.size %> item(s)</p>
58
+ <% end %>
59
+ </body>
60
+ </html>
61
+ HTML
62
+
63
+ attr_reader :template
64
+
65
+ def initialize(template = DEFAULT_TEMPLATE)
66
+ @template = ERB.new(template)
67
+ end
68
+
69
+ def generate(path:, files:)
70
+ template.result(binding)
71
+ end
72
+
73
+ def format_date(date)
74
+ date.strftime('%Y-%m-%d %H:%M')
75
+ end
76
+
77
+ def format_size(bytes)
78
+ return '0 B' if bytes.zero?
79
+
80
+ units = %w[B KB MB GB TB]
81
+ size = bytes.to_f
82
+ unit = 0
83
+
84
+ while size >= 1024 && unit < units.size - 1
85
+ size /= 1024
86
+ unit += 1
87
+ end
88
+
89
+ format("%.2f #{units[unit]}", size)
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aws-sdk-s3'
4
+
5
+ require_relative 'web_index_renderer'
6
+
7
+ # rubocop:disable Metrics/ParameterLists, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/BlockLength
8
+ module QuickAndRuby
9
+ module S3
10
+ class WebIndexer
11
+ attr_reader :bucket, :endpoint_url, :access_key, :secret_key, :region, :index_template
12
+
13
+ def initialize(bucket:, endpoint_url:, access_key:, secret_key:, region: 'us-east-1',
14
+ index_template: WebIndexRenderer.new, **extra)
15
+ @bucket = bucket
16
+ @endpoint_url = endpoint_url
17
+ @access_key = access_key
18
+ @secret_key = secret_key
19
+ @region = region
20
+ @index_template = index_template
21
+ @extra = extra
22
+ end
23
+
24
+ def index(*paths, nested: false)
25
+ paths.append('/') if paths.empty?
26
+
27
+ status = paths.inject(0) { |status, path| status + index_directory(path, nested: nested) }
28
+ status = 1 if status != 0
29
+ status
30
+ end
31
+
32
+ def list_directory(path, recursive: false)
33
+ objects = []
34
+ continuation_token = nil
35
+ prefix = path.end_with?('/') ? path : "#{path}/"
36
+ loop do
37
+ resp = s3_client.list_objects_v2(
38
+ bucket: bucket,
39
+ prefix: prefix,
40
+ delimiter: (recursive ? nil : '/'),
41
+ continuation_token: continuation_token
42
+ )
43
+
44
+ resp.common_prefixes&.each do |cp|
45
+ next unless cp.prefix.start_with?(prefix)
46
+
47
+ relativepath = cp.prefix.delete_prefix(prefix)
48
+
49
+ objects.append(
50
+ { filename: relativepath.chomp('/').split('/').last,
51
+ filename_relative_path: relativepath.to_s,
52
+ filename_realpath: "/#{bucket}/#{cp.prefix}",
53
+ last_modified: nil,
54
+ size: nil,
55
+ is_directory: true }
56
+ )
57
+ end
58
+
59
+ resp.contents.each do |object|
60
+ next if object.key == File.join(prefix, 'index.html')
61
+
62
+ relative_key = object.key.sub(prefix, '')
63
+ next if !recursive && relative_key.inlcude?('/') && !relative_key.empty?
64
+
65
+ objects.append(
66
+ { filename: relative_key,
67
+ filename_relative_path: relative_key,
68
+ filename_realpath: "/#{bucket}/#{object.key}",
69
+ last_modified: object.last_modified,
70
+ size: object.size,
71
+ is_directory: false }
72
+ )
73
+ end
74
+
75
+ continuation_token = resp.next_continuation_token
76
+ break unless continuation_token
77
+ end
78
+
79
+ objects
80
+ end
81
+
82
+ def index_directory(path, nested: false)
83
+ files = list_directory(path, recursive: nested)
84
+ index_content = index_template.generate(
85
+ path: path,
86
+ files: files
87
+ )
88
+ s3_client.put_object(bucket: bucket, key: "#{path}/index.html", body: index_content,
89
+ acl: 'public-read', content_type: 'text/html')
90
+ 0
91
+ end
92
+
93
+ def s3_client
94
+ @s3_client ||= Aws::S3::Client.new(
95
+ access_key_id: access_key,
96
+ secret_access_key: secret_key,
97
+ endpoint: endpoint_url,
98
+ region: region,
99
+ force_path_style: true,
100
+ ssl_verify_peer: false
101
+ )
102
+ end
103
+ end
104
+ end
105
+ end
106
+ # rubocop:enable Metrics/ParameterLists, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/BlockLength
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aws-sdk-s3'
4
+
5
+ require_relative 's3/web_indexer'
6
+
7
+ module QuickAndRuby
8
+ module S3
9
+
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module QuickAndRuby
2
- VERSION = '0.7.0'.freeze
2
+ VERSION = '0.8.0'.freeze
3
3
  end
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
  spec.homepage = 'https://github.com/ttych/quick_and_ruby'
16
16
  spec.license = 'MIT'
17
17
 
18
- spec.required_ruby_version = '> 3.1'
18
+ spec.required_ruby_version = '> 3.2'
19
19
 
20
20
  if spec.respond_to?(:metadata)
21
21
  spec.metadata['allowed_push_host'] = 'https://rubygems.org'
@@ -44,20 +44,22 @@ Gem::Specification.new do |spec|
44
44
 
45
45
  spec.add_dependency 'gli', '~> 2.22', '>= 2.22.2'
46
46
  # spec.add_dependency 'hexapdf', '~> 1.3'
47
+ spec.add_dependency 'aws-sdk-s3', '~> 1.205'
48
+ spec.add_dependency 'erb', '~> 6.0'
47
49
  spec.add_dependency 'ostruct', '~> 0.6', '>= 0.6.1'
48
50
  spec.add_dependency 'pdf-reader', '~> 2.14', '>= 2.14.1'
49
51
  spec.add_dependency 'webrick', '~> 1.9', '>= 1.9.1'
50
52
 
51
53
  spec.add_development_dependency 'bump', '~> 0.10'
52
- spec.add_development_dependency 'bundler', '~> 2.6', '>= 2.6.5'
53
- spec.add_development_dependency 'byebug', '~> 11.1', '>= 11.1.3'
54
- spec.add_development_dependency 'rake', '~> 13.3', '>= 13.3.0'
54
+ spec.add_development_dependency 'bundler', '~> 2.7', '>= 2.7.2'
55
+ spec.add_development_dependency 'byebug', '~> 12.0'
56
+ spec.add_development_dependency 'rake', '~> 13.3', '>= 13.3.1'
55
57
  spec.add_development_dependency 'reek', '~> 6.5'
56
- spec.add_development_dependency 'rspec', '~> 3.13', '>= 3.13.1'
57
- spec.add_development_dependency 'rubocop', '~> 1.76', '>= 1.76.1'
58
+ spec.add_development_dependency 'rspec', '~> 3.13', '>= 3.13.2'
59
+ spec.add_development_dependency 'rubocop', '~> 1.81', '>= 1.81.7'
58
60
  spec.add_development_dependency 'rubocop-rake', '~> 0.7', '>= 0.7.1'
59
- spec.add_development_dependency 'rubocop-rspec', '~> 3.6'
60
- spec.add_development_dependency 'ruby-lsp', '~> 0.24'
61
+ spec.add_development_dependency 'rubocop-rspec', '~> 3.8'
62
+ spec.add_development_dependency 'ruby-lsp', '~> 0.26', '>= 0.26.4'
61
63
  spec.add_development_dependency 'ruby-lsp-reek', '~> 0.3', '>= 0.3.1'
62
- spec.add_development_dependency 'ruby-lsp-rspec', '~> 0.1', '>= 0.1.25'
64
+ spec.add_development_dependency 'ruby-lsp-rspec', '~> 0.1', '>= 0.1.28'
63
65
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quick_and_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ttych
@@ -29,6 +29,34 @@ dependencies:
29
29
  - - ">="
30
30
  - !ruby/object:Gem::Version
31
31
  version: 2.22.2
32
+ - !ruby/object:Gem::Dependency
33
+ name: aws-sdk-s3
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - "~>"
37
+ - !ruby/object:Gem::Version
38
+ version: '1.205'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - "~>"
44
+ - !ruby/object:Gem::Version
45
+ version: '1.205'
46
+ - !ruby/object:Gem::Dependency
47
+ name: erb
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '6.0'
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '6.0'
32
60
  - !ruby/object:Gem::Dependency
33
61
  name: ostruct
34
62
  requirement: !ruby/object:Gem::Requirement
@@ -109,40 +137,34 @@ dependencies:
109
137
  requirements:
110
138
  - - "~>"
111
139
  - !ruby/object:Gem::Version
112
- version: '2.6'
140
+ version: '2.7'
113
141
  - - ">="
114
142
  - !ruby/object:Gem::Version
115
- version: 2.6.5
143
+ version: 2.7.2
116
144
  type: :development
117
145
  prerelease: false
118
146
  version_requirements: !ruby/object:Gem::Requirement
119
147
  requirements:
120
148
  - - "~>"
121
149
  - !ruby/object:Gem::Version
122
- version: '2.6'
150
+ version: '2.7'
123
151
  - - ">="
124
152
  - !ruby/object:Gem::Version
125
- version: 2.6.5
153
+ version: 2.7.2
126
154
  - !ruby/object:Gem::Dependency
127
155
  name: byebug
128
156
  requirement: !ruby/object:Gem::Requirement
129
157
  requirements:
130
158
  - - "~>"
131
159
  - !ruby/object:Gem::Version
132
- version: '11.1'
133
- - - ">="
134
- - !ruby/object:Gem::Version
135
- version: 11.1.3
160
+ version: '12.0'
136
161
  type: :development
137
162
  prerelease: false
138
163
  version_requirements: !ruby/object:Gem::Requirement
139
164
  requirements:
140
165
  - - "~>"
141
166
  - !ruby/object:Gem::Version
142
- version: '11.1'
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: 11.1.3
167
+ version: '12.0'
146
168
  - !ruby/object:Gem::Dependency
147
169
  name: rake
148
170
  requirement: !ruby/object:Gem::Requirement
@@ -152,7 +174,7 @@ dependencies:
152
174
  version: '13.3'
153
175
  - - ">="
154
176
  - !ruby/object:Gem::Version
155
- version: 13.3.0
177
+ version: 13.3.1
156
178
  type: :development
157
179
  prerelease: false
158
180
  version_requirements: !ruby/object:Gem::Requirement
@@ -162,7 +184,7 @@ dependencies:
162
184
  version: '13.3'
163
185
  - - ">="
164
186
  - !ruby/object:Gem::Version
165
- version: 13.3.0
187
+ version: 13.3.1
166
188
  - !ruby/object:Gem::Dependency
167
189
  name: reek
168
190
  requirement: !ruby/object:Gem::Requirement
@@ -186,7 +208,7 @@ dependencies:
186
208
  version: '3.13'
187
209
  - - ">="
188
210
  - !ruby/object:Gem::Version
189
- version: 3.13.1
211
+ version: 3.13.2
190
212
  type: :development
191
213
  prerelease: false
192
214
  version_requirements: !ruby/object:Gem::Requirement
@@ -196,27 +218,27 @@ dependencies:
196
218
  version: '3.13'
197
219
  - - ">="
198
220
  - !ruby/object:Gem::Version
199
- version: 3.13.1
221
+ version: 3.13.2
200
222
  - !ruby/object:Gem::Dependency
201
223
  name: rubocop
202
224
  requirement: !ruby/object:Gem::Requirement
203
225
  requirements:
204
226
  - - "~>"
205
227
  - !ruby/object:Gem::Version
206
- version: '1.76'
228
+ version: '1.81'
207
229
  - - ">="
208
230
  - !ruby/object:Gem::Version
209
- version: 1.76.1
231
+ version: 1.81.7
210
232
  type: :development
211
233
  prerelease: false
212
234
  version_requirements: !ruby/object:Gem::Requirement
213
235
  requirements:
214
236
  - - "~>"
215
237
  - !ruby/object:Gem::Version
216
- version: '1.76'
238
+ version: '1.81'
217
239
  - - ">="
218
240
  - !ruby/object:Gem::Version
219
- version: 1.76.1
241
+ version: 1.81.7
220
242
  - !ruby/object:Gem::Dependency
221
243
  name: rubocop-rake
222
244
  requirement: !ruby/object:Gem::Requirement
@@ -243,28 +265,34 @@ dependencies:
243
265
  requirements:
244
266
  - - "~>"
245
267
  - !ruby/object:Gem::Version
246
- version: '3.6'
268
+ version: '3.8'
247
269
  type: :development
248
270
  prerelease: false
249
271
  version_requirements: !ruby/object:Gem::Requirement
250
272
  requirements:
251
273
  - - "~>"
252
274
  - !ruby/object:Gem::Version
253
- version: '3.6'
275
+ version: '3.8'
254
276
  - !ruby/object:Gem::Dependency
255
277
  name: ruby-lsp
256
278
  requirement: !ruby/object:Gem::Requirement
257
279
  requirements:
258
280
  - - "~>"
259
281
  - !ruby/object:Gem::Version
260
- version: '0.24'
282
+ version: '0.26'
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: 0.26.4
261
286
  type: :development
262
287
  prerelease: false
263
288
  version_requirements: !ruby/object:Gem::Requirement
264
289
  requirements:
265
290
  - - "~>"
266
291
  - !ruby/object:Gem::Version
267
- version: '0.24'
292
+ version: '0.26'
293
+ - - ">="
294
+ - !ruby/object:Gem::Version
295
+ version: 0.26.4
268
296
  - !ruby/object:Gem::Dependency
269
297
  name: ruby-lsp-reek
270
298
  requirement: !ruby/object:Gem::Requirement
@@ -294,7 +322,7 @@ dependencies:
294
322
  version: '0.1'
295
323
  - - ">="
296
324
  - !ruby/object:Gem::Version
297
- version: 0.1.25
325
+ version: 0.1.28
298
326
  type: :development
299
327
  prerelease: false
300
328
  version_requirements: !ruby/object:Gem::Requirement
@@ -304,7 +332,7 @@ dependencies:
304
332
  version: '0.1'
305
333
  - - ">="
306
334
  - !ruby/object:Gem::Version
307
- version: 0.1.25
335
+ version: 0.1.28
308
336
  description: Set of small and standalone utilities in Ruby.
309
337
  email:
310
338
  - thomas.tych@gmail.com
@@ -317,6 +345,7 @@ executables:
317
345
  - json2yaml
318
346
  - proxy
319
347
  - quickpdf
348
+ - s3_web_indexer
320
349
  - yaml2json
321
350
  - yb
322
351
  extensions: []
@@ -340,6 +369,7 @@ files:
340
369
  - bin/json2yaml
341
370
  - bin/proxy
342
371
  - bin/quickpdf
372
+ - bin/s3_web_indexer
343
373
  - bin/yaml2json
344
374
  - bin/yb
345
375
  - lib/quick_and_ruby.rb
@@ -358,6 +388,9 @@ files:
358
388
  - lib/quick_and_ruby/proxy/arg_parser.rb
359
389
  - lib/quick_and_ruby/proxy/env_parser.rb
360
390
  - lib/quick_and_ruby/proxy/proxy.rb
391
+ - lib/quick_and_ruby/s3.rb
392
+ - lib/quick_and_ruby/s3/web_index_renderer.rb
393
+ - lib/quick_and_ruby/s3/web_indexer.rb
361
394
  - lib/quick_and_ruby/string.rb
362
395
  - lib/quick_and_ruby/string/case.rb
363
396
  - lib/quick_and_ruby/time.rb
@@ -384,14 +417,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
384
417
  requirements:
385
418
  - - ">"
386
419
  - !ruby/object:Gem::Version
387
- version: '3.1'
420
+ version: '3.2'
388
421
  required_rubygems_version: !ruby/object:Gem::Requirement
389
422
  requirements:
390
423
  - - ">="
391
424
  - !ruby/object:Gem::Version
392
425
  version: '0'
393
426
  requirements: []
394
- rubygems_version: 3.6.8
427
+ rubygems_version: 3.7.2
395
428
  specification_version: 4
396
429
  summary: Quick and Ruby utilities.
397
430
  test_files: []