vaguerent/lib/vagrant/util/curl_helper.rb
Chris Roberts d3fffd65d2 Prevent notifications on redirect to default store
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.
2021-03-15 15:21:07 -07:00

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