This also checks if the redirect notification has been displayed
before inspecting the source and location to prevent repeat checks
after the notification has been sent.
101 lines
3.5 KiB
Ruby
101 lines
3.5 KiB
Ruby
module Vagrant
|
|
module Util
|
|
class CurlHelper
|
|
|
|
# Hosts that do not require notification on redirect
|
|
SILENCED_HOSTS = [
|
|
"vagrantcloud-files-production.s3-accelerate.amazonaws.com".freeze,
|
|
"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
|
|
|
|
redirect_notify = false
|
|
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)
|
|
|
|
if !location_uri.host.nil? && !redirect_notify
|
|
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 location_host != source_host && !SILENCED_HOSTS.include?(location_host) && !SILENCED_HOSTS.include?(location_uri.host.to_s)
|
|
ui.rewriting do |_ui|
|
|
_ui.clear_line
|
|
_ui.detail "Download redirected to host: #{location_uri.host}"
|
|
end
|
|
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.rewriting do |ui|
|
|
ui.clear_line
|
|
ui.detail(output, new_line: false)
|
|
end
|
|
end
|
|
end
|
|
|
|
return data_proc
|
|
end
|
|
end
|
|
end
|
|
end
|