From ac8ad598232412fe363af45a7a3605c13bebb4c6 Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Tue, 26 Jun 2018 08:28:01 -0700 Subject: [PATCH] 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. --- plugins/pushes/ftp/errors.rb | 13 +++++++++++++ plugins/pushes/ftp/locales/en.yml | 5 +++++ plugins/pushes/ftp/push.rb | 18 ++++++++++++------ test/unit/plugins/pushes/ftp/push_test.rb | 5 +++++ 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 plugins/pushes/ftp/errors.rb diff --git a/plugins/pushes/ftp/errors.rb b/plugins/pushes/ftp/errors.rb new file mode 100644 index 000000000..111dd83af --- /dev/null +++ b/plugins/pushes/ftp/errors.rb @@ -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 diff --git a/plugins/pushes/ftp/locales/en.yml b/plugins/pushes/ftp/locales/en.yml index 0bbbe51f1..c5ba39869 100644 --- a/plugins/pushes/ftp/locales/en.yml +++ b/plugins/pushes/ftp/locales/en.yml @@ -9,3 +9,8 @@ en: config.push.define "ftp" do |push| push.%{attribute} = "..." 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. diff --git a/plugins/pushes/ftp/push.rb b/plugins/pushes/ftp/push.rb index 755304ee6..318c26d73 100644 --- a/plugins/pushes/ftp/push.rb +++ b/plugins/pushes/ftp/push.rb @@ -2,6 +2,7 @@ require "net/ftp" require "pathname" require_relative "adapter" +require_relative "errors" module VagrantPlugins module FTPPush @@ -17,12 +18,17 @@ module VagrantPlugins def push # 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 - files = Hash[*all_files.flat_map do |file| - relative_path = relative_path_for(file, config.dir) - destination = File.join(config.destination, relative_path) - file = File.expand_path(file, env.root_path) - [file, destination] - end] + files = nil + begin + files = Hash[*all_files.flat_map do |file| + relative_path = relative_path_for(file, config.dir) + destination = File.join(config.destination, relative_path) + file = File.expand_path(file, env.root_path) + [file, destination] + end] + rescue SystemStackError + raise Errors::TooManyFiles + end ftp = "#{config.username}@#{config.host}:#{config.destination}" env.ui.info "Uploading #{env.root_path} to #{ftp}" diff --git a/test/unit/plugins/pushes/ftp/push_test.rb b/test/unit/plugins/pushes/ftp/push_test.rb index ba69e0078..83509fb7d 100644 --- a/test/unit/plugins/pushes/ftp/push_test.rb +++ b/test/unit/plugins/pushes/ftp/push_test.rb @@ -73,6 +73,11 @@ describe VagrantPlugins::FTPPush::Push do subject.push expect(server.files).to eq(%w(Gemfile data.txt)) 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 describe "#connect" do