# Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: BUSL-1.1 require_relative "../../../base" require "fake_ftp" require Vagrant.source_root.join("plugins/pushes/ftp/push") describe VagrantPlugins::FTPPush::Push do include_context "unit" let(:env) { isolated_environment } let(:config) do double("config", host: "127.0.0.1:#{@port}", username: "sethvargo", password: "bacon", passive: false, secure: false, destination: "/var/www/site", ) end let(:ui) { Vagrant::UI::Silent.new } subject { described_class.new(env, config) } before do allow(env).to receive(:root_path) .and_return(File.expand_path("..", __FILE__)) allow(env).to receive(:ui) .and_return(ui) end describe "#push" do before(:all) do @server = nil with_random_port do |port1, port2| @port = port1 @server = FakeFtp::Server.new(port1, port2) end @server.start @dir = Dir.mktmpdir("vagrant-ftp-push") FileUtils.touch("#{@dir}/.hidden.rb") FileUtils.touch("#{@dir}/application.rb") FileUtils.touch("#{@dir}/config.rb") FileUtils.touch("#{@dir}/Gemfile") FileUtils.touch("#{@dir}/data.txt") FileUtils.mkdir("#{@dir}/empty_folder") end after(:all) do FileUtils.rm_rf(@dir) @server.stop end let(:server) { @server } before do allow(config).to receive(:dir) .and_return(@dir) allow(config).to receive(:includes) .and_return([]) allow(config).to receive(:excludes) .and_return(%w(*.rb)) end after do server.reset end it "pushes the files to the server" do subject.push expect(server.files).to eq(%w[/var/www/site/Gemfile /var/www/site/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 context "when VAGRANT_CWD is set to something relative" do # this will be the PWD for the test context let(:pwd) { Pathname.new(Dir.mktmpdir("vagrant-ftp-push-pwd")) } before do # this path should have a ../ in it since the pwd is another temp dir # and measuring path from one to the other. they're most likely to be # siblings relative_path = Pathname.new(@dir).relative_path_from(pwd) allow(env).to receive(:root_path) { relative_path.to_s } # reset config.dir to its default since it was set absolute above allow(config).to receive(:dir) { "." } end it "properly paths out the files to upload" do Vagrant::Util::SafeChdir.safe_chdir(pwd) do subject.push end expect(server.files).to eq(%w(/var/www/site/Gemfile /var/www/site/data.txt)) ensure FileUtils.rm_rf(pwd) end end end describe "#connect" do before do allow_any_instance_of(VagrantPlugins::FTPPush::FTPAdapter) .to receive(:connect) .and_yield(:ftp) allow_any_instance_of(VagrantPlugins::FTPPush::SFTPAdapter) .to receive(:connect) .and_yield(:sftp) end context "when secure is requested" do before do allow(config).to receive(:secure) .and_return(true) end it "yields a new SFTPAdapter" do expect { |b| subject.connect(&b) }.to yield_with_args(:sftp) end end context "when secure is not requested" do before do allow(config).to receive(:secure) .and_return(false) end it "yields a new FTPAdapter" do expect { |b| subject.connect(&b) }.to yield_with_args(:ftp) end end end describe "#all_files" do before(:all) do @dir = Dir.mktmpdir("vagrant-ftp-push-push-all-files") FileUtils.touch("#{@dir}/.hidden.rb") FileUtils.touch("#{@dir}/application.rb") FileUtils.touch("#{@dir}/config.rb") FileUtils.touch("#{@dir}/Gemfile") FileUtils.mkdir("#{@dir}/empty_folder") FileUtils.mkdir("#{@dir}/folder") FileUtils.mkdir("#{@dir}/folder/.git") FileUtils.touch("#{@dir}/folder/.git/config") FileUtils.touch("#{@dir}/folder/server.rb") end after(:all) do FileUtils.rm_rf(@dir) end let(:files) do subject.all_files.map do |file| file.sub("#{@dir}/", "") end end before do allow(config).to receive(:dir) .and_return(@dir) allow(config).to receive(:includes) .and_return(%w(not_a_file.rb still_not_a_file.rb)) allow(config).to receive(:excludes) .and_return(%w(*.rb)) end it "returns the list of real files + includes, without excludes" do expect(files).to eq(%w( Gemfile folder/.git/config )) end end describe "#includes_files" do before(:all) do @dir = Dir.mktmpdir("vagrant-ftp-push-includes-files") FileUtils.touch("#{@dir}/.hidden.rb") FileUtils.touch("#{@dir}/application.rb") FileUtils.touch("#{@dir}/config.rb") FileUtils.touch("#{@dir}/Gemfile") FileUtils.mkdir("#{@dir}/folder") FileUtils.mkdir("#{@dir}/folder/.git") FileUtils.touch("#{@dir}/folder/.git/config") FileUtils.touch("#{@dir}/folder/server.rb") end after(:all) do FileUtils.rm_rf(@dir) end let(:files) do subject.includes_files.map do |file| file.sub("#{@dir}/", "") end end before do allow(config).to receive(:dir) .and_return(@dir) end def set_includes(value) allow(config).to receive(:includes) .and_return(value) end it "includes the file" do set_includes(["Gemfile"]) expect(files).to eq(%w( Gemfile )) end it "includes the files that are subdirectories" do set_includes(["folder"]) expect(files).to eq(%w( folder folder/.git folder/.git/config folder/server.rb )) end it "includes files that match a pattern" do set_includes(["*.rb"]) expect(files).to eq(%w( .hidden.rb application.rb config.rb )) end end describe "#filter_excludes" do let(:dir) { "/root/dir" } let(:list) do %W( #{dir}/.hidden.rb #{dir}/application.rb #{dir}/config.rb #{dir}/Gemfile #{dir}/folder #{dir}/folder/.git #{dir}/folder/.git/config #{dir}/folder/server.rb /path/outside/you.rb /path/outside/me.rb /path/outside/folder/bacon.rb ) end before do allow(config).to receive(:dir) .and_return(dir) end it "excludes files" do subject.filter_excludes!(list, %w(*.rb)) expect(list).to eq(%W( #{dir}/Gemfile #{dir}/folder #{dir}/folder/.git #{dir}/folder/.git/config )) end it "excludes files in a directory" do subject.filter_excludes!(list, %w(folder)) expect(list).to eq(%W( #{dir}/.hidden.rb #{dir}/application.rb #{dir}/config.rb #{dir}/Gemfile /path/outside/you.rb /path/outside/me.rb /path/outside/folder/bacon.rb )) end it "excludes specific files in a directory" do subject.filter_excludes!(list, %w(/path/outside/folder/*.rb)) expect(list).to eq(%W( #{dir}/.hidden.rb #{dir}/application.rb #{dir}/config.rb #{dir}/Gemfile #{dir}/folder #{dir}/folder/.git #{dir}/folder/.git/config #{dir}/folder/server.rb /path/outside/you.rb /path/outside/me.rb )) end it "excludes files outside the #dir" do subject.filter_excludes!(list, %w(/path/outside)) expect(list).to eq(%W( #{dir}/.hidden.rb #{dir}/application.rb #{dir}/config.rb #{dir}/Gemfile #{dir}/folder #{dir}/folder/.git #{dir}/folder/.git/config #{dir}/folder/server.rb )) end end end