zip_tricks 5.0.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 327b846ccfc7d19442d21e145a2f767da91f0547381afe52be27db6709dee4a4
4
- data.tar.gz: 4d80718a715063f1cebad32471ab83e77d38a805f3ceed82793b922d0d3a877f
3
+ metadata.gz: 983b83d36f88a25db8276a74e45d506f801ac3ecdd64197fd6fbc98bdb39cb03
4
+ data.tar.gz: c74a8a3936f4afb1f71ad7775025b73ccd04d2db309df8942a20ff64e82cea81
5
5
  SHA512:
6
- metadata.gz: 982bc310eb658d67262c28efb043f1ddd3957db197ef1bcbe9108f3572431211069843221d36cf9b28231617d899249ad06be5b9c756189e8f0d383b168a340f
7
- data.tar.gz: 40fdde09881e02b5a816dae826554e14d76fb26a1bcf09cfcd053450668b34e2d3c63dc5bbf84417b6bdc44f021a35d38fdabd08d9ace5aabe1ff6c335b65e49
6
+ metadata.gz: 2b6eed391cd16c4077003535b0d7fb52e6930f351b230d31ba68aab2f05905df3987565aad76741083e888a91d054eaff3beab507117088b812b6c95f9ecf4f3
7
+ data.tar.gz: 9c4ad53ef462d28f8cdffcc439200788cb260e9d1b35ee231aed3b7979630d0c31881db95198a944c375c836678063e0db187fbfb3c2672819ad5e06d1023dc9
@@ -1,10 +1,6 @@
1
1
  rvm:
2
- - 2.1
3
- - 2.2.10
4
- - 2.3.7
5
- - 2.4.4
6
- - 2.5.4
7
- - 2.6.2
2
+ - 2.1.0
3
+ - 2.6.5
8
4
  - jruby-9.0
9
5
  sudo: false
10
6
  cache: bundler
@@ -1,3 +1,9 @@
1
+ ## 5.1.0
2
+
3
+ * Slightly rework `RemoteIO` and `RemoteUncap` and make sure they work correctly by spinning up a test webserver
4
+ to verify their operation. The changes to the documented API are fairly small so this is still marked as a minor
5
+ release.
6
+
1
7
  ## 5.0.0
2
8
 
3
9
  * Disable automatic filename deduplication by default, because it does not play nice with file/directory
@@ -8,14 +8,16 @@
8
8
  # actual fetches over HTTP and an object that expects a handful of IO methods to be
9
9
  # available.
10
10
  class ZipTricks::RemoteIO
11
- # @param fetcher[#request_object_size, #request_range] an object that perform fetches
12
- def initialize(fetcher = :NOT_SET)
11
+ # @param url[String, URI] the HTTP/HTTPS URL of the object to be retrieved
12
+ def initialize(url)
13
13
  @pos = 0
14
- @fetcher = fetcher
15
- @remote_size = false
14
+ @uri = URI(url)
15
+ @remote_size = nil
16
16
  end
17
17
 
18
18
  # Emulates IO#seek
19
+ # @param offset[Integer] absolute offset in the remote resource to seek to
20
+ # @param mode[Integer] The seek mode (only SEEK_SET is supported)
19
21
  def seek(offset, mode = IO::SEEK_SET)
20
22
  raise "Unsupported read mode #{mode}" unless mode == IO::SEEK_SET
21
23
  @remote_size ||= request_object_size
@@ -25,7 +27,7 @@ class ZipTricks::RemoteIO
25
27
 
26
28
  # Emulates IO#size.
27
29
  #
28
- # @return [Fixnum] the size of the remote resource
30
+ # @return [Integer] the size of the remote resource
29
31
  def size
30
32
  @remote_size ||= request_object_size
31
33
  end
@@ -39,21 +41,20 @@ class ZipTricks::RemoteIO
39
41
  # @param n_bytes[Fixnum, nil] how many bytes to read, or `nil` to read all the way to the end
40
42
  # @return [String] the read bytes
41
43
  def read(n_bytes = nil)
42
- @remote_size ||= request_object_size
43
-
44
44
  # If the resource is empty there is nothing to read
45
- return if @remote_size.zero?
45
+ return if size.zero?
46
46
 
47
- maximum_avaialable = @remote_size - @pos
47
+ maximum_avaialable = size - @pos
48
48
  n_bytes ||= maximum_avaialable # nil == read to the end of file
49
49
  return '' if n_bytes.zero?
50
50
  raise ArgumentError, "No negative reads(#{n_bytes})" if n_bytes < 0
51
51
 
52
52
  n_bytes = clamp(0, n_bytes, maximum_avaialable)
53
53
 
54
- read_n_bytes_from_remote(@pos, n_bytes).tap do |data|
54
+ http_range = (@pos..(@pos + n_bytes - 1))
55
+ request_range(http_range).tap do |data|
55
56
  raise "Remote read returned #{data.bytesize} bytes instead of #{n_bytes} as requested" if data.bytesize != n_bytes
56
- @pos = clamp(0, @pos + data.bytesize, @remote_size)
57
+ @pos = clamp(0, @pos + data.bytesize, size)
57
58
  end
58
59
  end
59
60
 
@@ -66,23 +67,41 @@ class ZipTricks::RemoteIO
66
67
 
67
68
  protected
68
69
 
70
+ # Only used internally when reading the remote ZIP.
71
+ #
72
+ # @param range[Range] the HTTP range of data to fetch from remote
73
+ # @return [String] the response body of the ranged request
69
74
  def request_range(range)
70
- @fetcher.request_range(range)
75
+ http = Net::HTTP.start(@uri.hostname, @uri.port)
76
+ request = Net::HTTP::Get.new(@uri)
77
+ request.range = range
78
+ response = http.request(request)
79
+ case response.code
80
+ when "206", "200"
81
+ response.body
82
+ else
83
+ raise "Remote at #{@uri} replied with code #{response.code}"
84
+ end
71
85
  end
72
86
 
87
+ # For working with S3 it is a better idea to perform a GET request for one byte, since doing a HEAD
88
+ # request needs a different permission - and standard GET presigned URLs are not allowed to perform it
89
+ #
90
+ # @return [Integer] the size of the remote resource, parsed either from Content-Length or Content-Range header
73
91
  def request_object_size
74
- @fetcher.request_object_size
75
- end
76
-
77
- # Reads N bytes at offset from remote
78
- def read_n_bytes_from_remote(start_at, n_bytes)
79
- range = (start_at..(start_at + n_bytes - 1))
80
- request_range(range)
81
- end
82
-
83
- # Reads the Content-Length and caches it
84
- def remote_size
85
- @remote_size ||= request_object_size
92
+ http = Net::HTTP.start(@uri.hostname, @uri.port)
93
+ request = Net::HTTP::Get.new(@uri)
94
+ request.range = 0..0
95
+ response = http.request(request)
96
+ case response.code
97
+ when "206"
98
+ content_range_header_value = response['Content-Range']
99
+ content_range_header_value.split('/').last.to_i
100
+ when "200"
101
+ response['Content-Length'].to_i
102
+ else
103
+ raise "Remote at #{@uri} replied with code #{response.code}"
104
+ end
86
105
  end
87
106
 
88
107
  private
@@ -7,42 +7,16 @@
7
7
  #
8
8
  # Please read the security warning in `FileReader` _VERY CAREFULLY_
9
9
  # before you use this module.
10
- class ZipTricks::RemoteUncap
10
+ module ZipTricks::RemoteUncap
11
11
  # @param uri[String] the HTTP(S) URL to read the ZIP footer from
12
12
  # @param reader_class[Class] which class to use for reading
13
13
  # @param options_for_zip_reader[Hash] any additional options to give to
14
14
  # {ZipTricks::FileReader} when reading
15
15
  # @return [Array<ZipTricks::FileReader::ZipEntry>] metadata about the
16
16
  # files within the remote archive
17
- def self.files_within_zip_at(uri,
18
- reader_class: ZipTricks::FileReader,
19
- **options_for_zip_reader)
20
- fetcher = new(uri)
21
- fake_io = ZipTricks::RemoteIO.new(fetcher)
17
+ def self.files_within_zip_at(uri, reader_class: ZipTricks::FileReader, **options_for_zip_reader)
18
+ fake_io = ZipTricks::RemoteIO.new(uri)
22
19
  reader = reader_class.new
23
20
  reader.read_zip_structure(io: fake_io, **options_for_zip_reader)
24
21
  end
25
-
26
- def initialize(uri)
27
- @uri = URI(uri)
28
- end
29
-
30
- # Only used internally when reading the remote ZIP.
31
- #
32
- # @param range[Range] the HTTP range of data to fetch from remote
33
- # @return [String] the response body of the ranged request
34
- def request_range(range)
35
- request = Net::HTTP::Get.new(@uri)
36
- request.range = range
37
- http = Net::HTTP.start(@uri.hostname, @uri.port)
38
- http.request(request).body
39
- end
40
-
41
- # Only used internally when reading the remote ZIP.
42
- #
43
- # @return [Fixnum] the byte size of the ranged request
44
- def request_object_size
45
- http = Net::HTTP.start(@uri.hostname, @uri.port)
46
- http.request_head(@uri)['Content-Length'].to_i
47
- end
48
22
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ZipTricks
4
- VERSION = '5.0.0'
4
+ VERSION = '5.1.0'
5
5
  end
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
31
31
  spec.require_paths = ['lib']
32
32
 
33
33
  spec.add_development_dependency 'bundler'
34
- spec.add_development_dependency 'rubyzip', '>= 1.2.2'
34
+ spec.add_development_dependency 'rubyzip', '~> 1', '>= 1.2.2'
35
35
  spec.add_development_dependency 'terminal-table'
36
36
  spec.add_development_dependency 'range_utils'
37
37
 
@@ -44,4 +44,5 @@ Gem::Specification.new do |spec|
44
44
  spec.add_development_dependency 'allocation_stats', '~> 0.1.5'
45
45
  spec.add_development_dependency 'yard', '~> 0.9'
46
46
  spec.add_development_dependency 'wetransfer_style', '0.6.0'
47
+ spec.add_development_dependency 'puma'
47
48
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zip_tricks
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2019-11-01 00:00:00.000000000 Z
14
+ date: 2020-02-04 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -31,6 +31,9 @@ dependencies:
31
31
  name: rubyzip
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
+ - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: '1'
34
37
  - - ">="
35
38
  - !ruby/object:Gem::Version
36
39
  version: 1.2.2
@@ -38,6 +41,9 @@ dependencies:
38
41
  prerelease: false
39
42
  version_requirements: !ruby/object:Gem::Requirement
40
43
  requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1'
41
47
  - - ">="
42
48
  - !ruby/object:Gem::Version
43
49
  version: 1.2.2
@@ -195,6 +201,20 @@ dependencies:
195
201
  - - '='
196
202
  - !ruby/object:Gem::Version
197
203
  version: 0.6.0
204
+ - !ruby/object:Gem::Dependency
205
+ name: puma
206
+ requirement: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ version: '0'
211
+ type: :development
212
+ prerelease: false
213
+ version_requirements: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: '0'
198
218
  description: Stream out ZIP files from Ruby
199
219
  email:
200
220
  - me@julik.nl