down 4.2.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 16efde61a43b30f68aa001eb0f06bdc8403d2e7c
4
- data.tar.gz: 0e56e5adc2bb0bc0387f7198af7b0063ab577aef
3
+ metadata.gz: 4fe68b913e3b94078cfc74c7599ef57cab7d4ac2
4
+ data.tar.gz: f2cc86395be9ee08f188bd40d90cac2b9ae0ab59
5
5
  SHA512:
6
- metadata.gz: b2f9108523aea427699de88ffc65f8e6d114d75850317f07bce6c3c7019e7f5add1b52ee660e57c109b526d1a8ea42f81c0944564c17ba6f6b18d537f51f4a69
7
- data.tar.gz: 535dbb6812caba261e692ec713bf25df4aa57ec97027a1b74474aef060b2c9c182267a0d8008210e760d66826e7c978b898efdf4dc0d66355507c39755d84944
6
+ metadata.gz: 6a28ee64408befa22c4fb0eb51a5863daaa83555bb4dc5a72c3ee536cb32a2aaa0781cf163284144cdf42c179fdf0f3530bf5c5e804b18e6ff2dea2ab3e48fb6
7
+ data.tar.gz: 45d8928e426182b463dee00daa5956e0a828a547e672b7e611cf135e333da696aa19fdf7f29eff45ce46580918c48c1720c1f5727d4d8bf01e534b2aa4d9f093
@@ -1,3 +1,13 @@
1
+ ## 4.3.0 (2018-03-11)
2
+
3
+ * Accept CLI arguments as a list of symbols in `Down::Wget#download` (@janko-m)
4
+
5
+ * Avoid potential URL parsing errors in `Down::Http::DownloadedFile#filename_from_url` (@janko-m)
6
+
7
+ * Make memory usage of `Down::Wget#download` constant (@janko-m)
8
+
9
+ * Add `:destination` option to `Down.download` for specifying download destination (@janko-m)
10
+
1
11
  ## 4.2.1 (2018-01-29)
2
12
 
3
13
  * Reduce memory allocation in `Down::ChunkedIO` by 10x when buffer string is used (@janko-m)
data/README.md CHANGED
@@ -41,7 +41,7 @@ Down allows you to pass a `:max_size` option:
41
41
 
42
42
  ```rb
43
43
  Down.download("http://example.com/image.jpg", max_size: 5 * 1024 * 1024) # 5 MB
44
- # raises Down::TooLarge
44
+ # !~> Down::TooLarge
45
45
  ```
46
46
 
47
47
  What is the advantage over simply checking size after downloading? Well, Down
@@ -49,6 +49,17 @@ terminates the download very early, as soon as it gets the `Content-Length`
49
49
  header. And if the `Content-Length` header is missing, Down will terminate the
50
50
  download as soon as the downloaded content surpasses the maximum size.
51
51
 
52
+ ### Destination
53
+
54
+ By default the remote file will be downloaded into a temporary location and
55
+ returned as a `Tempfile`. If you would like the file to be downloaded to a
56
+ specific location on disk, you can specify the `:destination` option:
57
+
58
+ ```rb
59
+ Down.download("http://example.com/image.jpg", destination: "/path/to/destination")
60
+ #=> nil
61
+ ```
62
+
52
63
  ### Basic authentication
53
64
 
54
65
  `Down.download` and `Down.open` will automatically detect and apply HTTP basic
@@ -6,7 +6,7 @@ Gem::Specification.new do |spec|
6
6
 
7
7
  spec.required_ruby_version = ">= 2.1"
8
8
 
9
- spec.summary = "Robust streaming downloads using net/http."
9
+ spec.summary = "Robust streaming downloads using Net::HTTP, HTTP.rb or wget."
10
10
  spec.homepage = "https://github.com/janko-m/down"
11
11
  spec.authors = ["Janko Marohnić"]
12
12
  spec.email = ["janko.marohnic@gmail.com"]
@@ -4,6 +4,8 @@ require "down/version"
4
4
  require "down/chunked_io"
5
5
  require "down/errors"
6
6
 
7
+ require "fileutils"
8
+
7
9
  module Down
8
10
  class Backend
9
11
  def self.download(*args, &block)
@@ -13,5 +15,17 @@ module Down
13
15
  def self.open(*args, &block)
14
16
  new.open(*args, &block)
15
17
  end
18
+
19
+ private
20
+
21
+ def download_result(tempfile, destination)
22
+ if destination
23
+ tempfile.close
24
+ FileUtils.mv tempfile.path, destination
25
+ nil
26
+ else
27
+ tempfile
28
+ end
29
+ end
16
30
  end
17
31
  end
@@ -276,8 +276,8 @@ module Down
276
276
 
277
277
  # Creates a Fiber wrapper around the underlying enumerator. The advantage
278
278
  # of using a Fiber here is that we can terminate the chunk retrieval, in a
279
- # way that executes any cleanup code that the enumerator carries. At the
280
- # end of iteration the :on_close callback is executed if one was specified.
279
+ # way that executes any cleanup code that the enumerator potentially
280
+ # carries. At the end of iteration the :on_close callback is executed.
281
281
  def chunks_fiber
282
282
  @chunks_fiber ||= Fiber.new do
283
283
  begin
@@ -19,7 +19,7 @@ module Down
19
19
  @options = { headers: { "User-Agent" => "Down/#{Down::VERSION}" }, follow: { max_hops: 2 } }.merge(options)
20
20
  end
21
21
 
22
- def download(url, max_size: nil, progress_proc: nil, content_length_proc: nil, **options, &block)
22
+ def download(url, max_size: nil, progress_proc: nil, content_length_proc: nil, destination: nil, **options, &block)
23
23
  io = open(url, **options, rewindable: false, &block)
24
24
 
25
25
  content_length_proc.call(io.size) if content_length_proc && io.size
@@ -32,7 +32,9 @@ module Down
32
32
  tempfile = Tempfile.new(["down-http", extname], binmode: true)
33
33
 
34
34
  until io.eof?
35
- tempfile.write(io.readpartial(nil, buffer ||= String.new))
35
+ chunk = io.readpartial(nil, buffer ||= String.new)
36
+
37
+ tempfile.write(chunk)
36
38
 
37
39
  progress_proc.call(tempfile.size) if progress_proc
38
40
 
@@ -47,7 +49,7 @@ module Down
47
49
  tempfile.url = io.data[:response].uri.to_s
48
50
  tempfile.headers = io.data[:headers]
49
51
 
50
- tempfile
52
+ download_result(tempfile, destination)
51
53
  rescue
52
54
  tempfile.close! if tempfile
53
55
  raise
@@ -152,7 +154,7 @@ module Down
152
154
  private
153
155
 
154
156
  def content_type_header
155
- ::HTTP::ContentType.parse(headers["Content-Type"])
157
+ HTTP::ContentType.parse(headers["Content-Type"])
156
158
  end
157
159
 
158
160
  def filename_from_content_disposition
@@ -163,7 +165,7 @@ module Down
163
165
  end
164
166
 
165
167
  def filename_from_url
166
- path = URI(url).path
168
+ path = HTTP::URI.parse(url).path
167
169
  filename = path.split("/").last
168
170
  CGI.unescape(filename) if filename
169
171
  end
@@ -22,6 +22,7 @@ module Down
22
22
  max_redirects = options.delete(:max_redirects)
23
23
  progress_proc = options.delete(:progress_proc)
24
24
  content_length_proc = options.delete(:content_length_proc)
25
+ destination = options.delete(:destination)
25
26
 
26
27
  open_uri_options = {
27
28
  content_length_proc: proc { |size|
@@ -70,7 +71,7 @@ module Down
70
71
  OpenURI::Meta.init tempfile, open_uri_file # add back open-uri methods
71
72
  tempfile.extend Down::NetHttp::DownloadedFile
72
73
 
73
- tempfile
74
+ download_result(tempfile, destination)
74
75
  end
75
76
 
76
77
  def open(url, options = {})
@@ -1,5 +1,5 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Down
4
- VERSION = "4.2.1"
4
+ VERSION = "4.3.0"
5
5
  end
@@ -19,8 +19,8 @@ module Down
19
19
  @arguments = [max_redirect: 2, user_agent: "Down/#{Down::VERSION}"] + arguments
20
20
  end
21
21
 
22
- def download(url, *args, max_size: nil, content_length_proc: nil, progress_proc: nil, **options)
23
- io = open(url, **options, rewindable: false)
22
+ def download(url, *args, max_size: nil, content_length_proc: nil, progress_proc: nil, destination: nil, **options)
23
+ io = open(url, *args, **options, rewindable: false)
24
24
 
25
25
  content_length_proc.call(io.size) if content_length_proc && io.size
26
26
 
@@ -32,7 +32,9 @@ module Down
32
32
  tempfile = Tempfile.new(["down-wget", extname], binmode: true)
33
33
 
34
34
  until io.eof?
35
- tempfile.write(io.readpartial)
35
+ chunk = io.readpartial(nil, buffer ||= String.new)
36
+
37
+ tempfile.write(chunk)
36
38
 
37
39
  progress_proc.call(tempfile.size) if progress_proc
38
40
 
@@ -47,7 +49,7 @@ module Down
47
49
  tempfile.url = url
48
50
  tempfile.headers = io.data[:headers]
49
51
 
50
- tempfile
52
+ download_result(tempfile, destination)
51
53
  rescue
52
54
  tempfile.close! if tempfile
53
55
  raise
@@ -105,10 +107,12 @@ module Down
105
107
  command = %W[wget --no-verbose --save-headers -O -]
106
108
 
107
109
  options = @arguments.grep(Hash).inject({}, :merge).merge(options)
108
- args = @arguments.grep(Symbol) + args
110
+ args = @arguments.grep(->(o){!o.is_a?(Hash)}) + args
109
111
 
110
112
  (args + options.to_a).each do |option, value|
111
- if option.length == 1
113
+ if option.is_a?(String)
114
+ command << option
115
+ elsif option.length == 1
112
116
  command << "-#{option}"
113
117
  else
114
118
  command << "--#{option.to_s.gsub("_", "-")}"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: down
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.1
4
+ version: 4.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-29 00:00:00.000000000 Z
11
+ date: 2018-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -150,5 +150,5 @@ rubyforge_project:
150
150
  rubygems_version: 2.6.11
151
151
  signing_key:
152
152
  specification_version: 4
153
- summary: Robust streaming downloads using net/http.
153
+ summary: Robust streaming downloads using Net::HTTP, HTTP.rb or wget.
154
154
  test_files: []