Provide custom error when attempting to push too many files with FTP

When the configured directory for FTP push has too many files, it will
generate an exception and fail due to a stack overflow. When this happens
just rescue out the exception and re-raise a custom error to provide
some context to the user on the actual problem.
This commit is contained in:
Chris Roberts 2018-06-26 08:28:01 -07:00
parent 85acf0cac7
commit ac8ad59823
4 changed files with 35 additions and 6 deletions

View File

@ -0,0 +1,13 @@
module VagrantPlugins
module FTPPush
module Errors
class Error < Vagrant::Errors::VagrantError
error_namespace("ftp_push.errors")
end
class TooManyFiles < Error
error_key(:too_many_files)
end
end
end
end

View File

@ -9,3 +9,8 @@ en:
config.push.define "ftp" do |push| config.push.define "ftp" do |push|
push.%{attribute} = "..." push.%{attribute} = "..."
end end
too_many_files: |-
The configured directory for Vagrant FTP push contains too many files
to successfully complete the command. This can be resolved by either
removing extraneous files from the configured directory, or updating
the `dir` configuration option to a subdirectory.

View File

@ -2,6 +2,7 @@ require "net/ftp"
require "pathname" require "pathname"
require_relative "adapter" require_relative "adapter"
require_relative "errors"
module VagrantPlugins module VagrantPlugins
module FTPPush module FTPPush
@ -17,12 +18,17 @@ module VagrantPlugins
def push def push
# Grab files early so if there's an exception or issue, we don't have to # Grab files early so if there's an exception or issue, we don't have to
# wait and close the (S)FTP connection as well # wait and close the (S)FTP connection as well
files = nil
begin
files = Hash[*all_files.flat_map do |file| files = Hash[*all_files.flat_map do |file|
relative_path = relative_path_for(file, config.dir) relative_path = relative_path_for(file, config.dir)
destination = File.join(config.destination, relative_path) destination = File.join(config.destination, relative_path)
file = File.expand_path(file, env.root_path) file = File.expand_path(file, env.root_path)
[file, destination] [file, destination]
end] end]
rescue SystemStackError
raise Errors::TooManyFiles
end
ftp = "#{config.username}@#{config.host}:#{config.destination}" ftp = "#{config.username}@#{config.host}:#{config.destination}"
env.ui.info "Uploading #{env.root_path} to #{ftp}" env.ui.info "Uploading #{env.root_path} to #{ftp}"

View File

@ -73,6 +73,11 @@ describe VagrantPlugins::FTPPush::Push do
subject.push subject.push
expect(server.files).to eq(%w(Gemfile data.txt)) expect(server.files).to eq(%w(Gemfile data.txt))
end end
it "raises informative exception when too many files to process" do
expect(subject).to receive(:all_files).and_raise(SystemStackError)
expect{ subject.push }.to raise_error(VagrantPlugins::FTPPush::Errors::TooManyFiles)
end
end end
describe "#connect" do describe "#connect" do