mirror of
https://github.com/hashicorp/vagrant.git
synced 2026-06-09 00:32:06 -04:00
Remove customized require behaviors and modify the bin executable to check for missing tools that Vagrant expects to exist when running outside of an installer.
137 lines
4.2 KiB
Ruby
137 lines
4.2 KiB
Ruby
# Copyright (c) HashiCorp, Inc.
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
require "net/ftp"
|
|
require "pathname"
|
|
|
|
require_relative "adapter"
|
|
require_relative "errors"
|
|
|
|
module VagrantPlugins
|
|
module FTPPush
|
|
class Push < Vagrant.plugin("2", :push)
|
|
IGNORED_FILES = %w(. ..).freeze
|
|
DEFAULT_EXCLUDES = %w(.git .hg .svn .vagrant).freeze
|
|
|
|
def initialize(*)
|
|
super
|
|
@logger = Log4r::Logger.new("vagrant::pushes::ftp")
|
|
end
|
|
|
|
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 = nil
|
|
begin
|
|
files = Hash[*all_files.flat_map do |file|
|
|
relative_path = relative_path_for(file, base_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 #{files.length} files to #{env.root_path} to #{ftp}"
|
|
|
|
connect do |ftp|
|
|
files.each do |local, remote|
|
|
env.ui.info "Uploading #{local} => #{remote}"
|
|
ftp.upload(local, remote)
|
|
end
|
|
end
|
|
end
|
|
|
|
# Helper method for creating the FTP or SFTP connection.
|
|
# @yield [Adapter]
|
|
def connect(&block)
|
|
klass = config.secure ? SFTPAdapter : FTPAdapter
|
|
ftp = klass.new(config.host, config.username, config.password,
|
|
passive: config.passive)
|
|
ftp.connect(&block)
|
|
end
|
|
|
|
# The list of all files that should be pushed by this push. This method
|
|
# only returns **files**, not folders or symlinks!
|
|
# @return [Array<String>]
|
|
def all_files
|
|
files = glob("#{base_dir}/**/*") + includes_files
|
|
filter_excludes!(files, config.excludes)
|
|
files.reject! { |f| !File.file?(f) }
|
|
files
|
|
end
|
|
|
|
# The list of files to include in addition to those specified in `dir`.
|
|
# @return [Array<String>]
|
|
def includes_files
|
|
includes = config.includes.flat_map do |i|
|
|
path = absolute_path_for(i, base_dir)
|
|
[path, "#{path}/**/*"]
|
|
end
|
|
|
|
glob("{#{includes.join(",")}}")
|
|
end
|
|
|
|
# Filter the excludes out of the given list. This method modifies the
|
|
# given list in memory!
|
|
#
|
|
# @param [Array<String>] list
|
|
# the filepaths
|
|
# @param [Array<String>] excludes
|
|
# the exclude patterns or files
|
|
def filter_excludes!(list, excludes)
|
|
excludes = Array(excludes)
|
|
excludes = excludes + DEFAULT_EXCLUDES
|
|
excludes = excludes.flat_map { |e| [e, "#{e}/*"] }
|
|
|
|
list.reject! do |file|
|
|
basename = relative_path_for(file, config.dir)
|
|
|
|
# Handle the special case where the file is outside of the working
|
|
# directory...
|
|
if basename.start_with?("../")
|
|
basename = file
|
|
end
|
|
|
|
excludes.any? { |e| File.fnmatch?(e, basename, File::FNM_DOTMATCH) }
|
|
end
|
|
end
|
|
|
|
# Get the list of files that match the given pattern.
|
|
# @return [Array<String>]
|
|
def glob(pattern)
|
|
Dir.glob(pattern, File::FNM_DOTMATCH).sort.reject do |file|
|
|
IGNORED_FILES.include?(File.basename(file))
|
|
end
|
|
end
|
|
|
|
# The absolute path to the given `path` and `parent`, unless the given
|
|
# path is absolute.
|
|
# @return [String]
|
|
def absolute_path_for(path, parent)
|
|
path = Pathname.new(path)
|
|
return path if path.absolute?
|
|
File.expand_path(path, parent)
|
|
end
|
|
|
|
# The relative path from the given `parent`. If files exist on another
|
|
# device, this will probably blow up.
|
|
# @return [String]
|
|
def relative_path_for(path, parent)
|
|
Pathname.new(path).relative_path_from(Pathname.new(parent)).to_s
|
|
rescue ArgumentError
|
|
return path
|
|
end
|
|
|
|
def base_dir
|
|
if Pathname.new(config.dir).absolute?
|
|
config.dir
|
|
else
|
|
File.join(File.expand_path(env.root_path), config.dir)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|