97 lines
3.2 KiB
Ruby
97 lines
3.2 KiB
Ruby
module Vagrant
|
|
module Util
|
|
class CurlHelper
|
|
|
|
# Hosts that do not require notification on redirect
|
|
SILENCED_HOSTS = [
|
|
"vagrantcloud.com".freeze,
|
|
"vagrantup.com".freeze
|
|
].freeze
|
|
|
|
def self.capture_output_proc(logger, ui, source=nil)
|
|
progress_data = ""
|
|
progress_regexp = /^\r\s*(\d.+?)\r/m
|
|
|
|
# Setup the proc that'll receive the real-time data from
|
|
# the downloader.
|
|
data_proc = Proc.new do |type, data|
|
|
# Type will always be "stderr" because that is the only
|
|
# type of data we're subscribed for notifications.
|
|
|
|
# Accumulate progress_data
|
|
progress_data << data
|
|
|
|
while true
|
|
# If the download has been redirected and we are no longer downloading
|
|
# from the original host, notify the user that the target host has
|
|
# changed from the source.
|
|
if progress_data.include?("Location")
|
|
location = progress_data.scan(/(^|[^\w-])Location: (.+?)$/m).flatten.compact.last.to_s.strip
|
|
if !location.empty?
|
|
location_uri = URI.parse(location)
|
|
|
|
unless location_uri.host.nil?
|
|
redirect_notify = false
|
|
logger.info("download redirected to #{location}")
|
|
source_uri = URI.parse(source)
|
|
source_host = source_uri.host.to_s.split(".", 2).last
|
|
location_host = location_uri.host.to_s.split(".", 2).last
|
|
if !redirect_notify && location_host != source_host && !SILENCED_HOSTS.include?(location_host)
|
|
ui.clear_line
|
|
ui.detail "Download redirected to host: #{location_uri.host}"
|
|
end
|
|
redirect_notify = true
|
|
end
|
|
end
|
|
progress_data.replace("")
|
|
break
|
|
end
|
|
# If we have a full amount of column data (two "\r") then
|
|
# we report new progress reports. Otherwise, just keep
|
|
# accumulating.
|
|
match = nil
|
|
check_match = true
|
|
|
|
while check_match
|
|
check_match = progress_regexp.match(progress_data)
|
|
if check_match
|
|
data = check_match[1].to_s
|
|
stop = progress_data.index(data) + data.length
|
|
progress_data.slice!(0, stop)
|
|
|
|
match = check_match
|
|
end
|
|
end
|
|
|
|
break if !match
|
|
|
|
# Ignore the first \r and split by whitespace to grab the columns
|
|
columns = data.strip.split(/\s+/)
|
|
|
|
# COLUMN DATA:
|
|
#
|
|
# 0 - % total
|
|
# 1 - Total size
|
|
# 2 - % received
|
|
# 3 - Received size
|
|
# 4 - % transferred
|
|
# 5 - Transferred size
|
|
# 6 - Average download speed
|
|
# 7 - Average upload speed
|
|
# 9 - Total time
|
|
# 9 - Time spent
|
|
# 10 - Time left
|
|
# 11 - Current speed
|
|
|
|
output = "Progress: #{columns[0]}% (Rate: #{columns[11]}/s, Estimated time remaining: #{columns[10]})"
|
|
ui.clear_line
|
|
ui.detail(output, new_line: false)
|
|
end
|
|
end
|
|
|
|
return data_proc
|
|
end
|
|
end
|
|
end
|
|
end
|