Speed up file syncing using zip/tgz
This commit is contained in:
parent
d7456413ff
commit
c0102812f4
|
@ -44,7 +44,7 @@ module VagrantPlugins
|
|||
"rm -f '#{compressed_file}'",
|
||||
"rm -rf '#{extract_dir}'"
|
||||
]
|
||||
cmds.each{ |cmd| comm.execute(cmd) }
|
||||
cmds.each{ |cmd| comm.execute(cmd, sudo: opts[:sudo] || false) }
|
||||
true
|
||||
end
|
||||
|
||||
|
@ -68,7 +68,7 @@ module VagrantPlugins
|
|||
"rm -f '#{compressed_file}'",
|
||||
"rm -rf '#{extract_dir}'"
|
||||
]
|
||||
cmds.each{ |cmd| comm.execute(cmd) }
|
||||
cmds.each{ |cmd| comm.execute(cmd, sudo: opts[:sudo] || false) }
|
||||
true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -46,7 +46,7 @@ module VagrantPlugins
|
|||
"rm -f '#{compressed_file}'",
|
||||
"rm -rf '#{extract_dir}'"
|
||||
]
|
||||
cmds.each{ |cmd| comm.execute(cmd) }
|
||||
cmds.each{ |cmd| comm.execute(cmd, sudo: opts[:sudo] || false) }
|
||||
true
|
||||
end
|
||||
|
||||
|
@ -70,7 +70,7 @@ module VagrantPlugins
|
|||
"rm -f '#{compressed_file}'",
|
||||
"rm -rf '#{extract_dir}'"
|
||||
]
|
||||
cmds.each{ |cmd| comm.execute(cmd) }
|
||||
cmds.each{ |cmd| comm.execute(cmd, sudo: opts[:sudo] || false) }
|
||||
true
|
||||
end
|
||||
|
||||
|
@ -78,7 +78,7 @@ module VagrantPlugins
|
|||
#
|
||||
# @param [Vagrant::Machine] machine Vagrant guest machine
|
||||
# @param [array] paths to create on guest
|
||||
def self.create_directories(machine, dirs)
|
||||
def self.create_directories(machine, dirs, opts={})
|
||||
return [] if dirs.empty?
|
||||
|
||||
remote_fn = create_tmp_path(machine, {})
|
||||
|
@ -93,7 +93,7 @@ module VagrantPlugins
|
|||
tmp.unlink
|
||||
end
|
||||
created_paths = []
|
||||
machine.communicate.sudo("bash -c 'while IFS= read -r line
|
||||
machine.communicate.execute("bash -c 'while IFS= read -r line
|
||||
do
|
||||
if [ ! -z \"${line}\" ] && [ ! -d \"${line}\" ]; then
|
||||
if [ -f \"${line}\" ]; then
|
||||
|
@ -102,7 +102,7 @@ module VagrantPlugins
|
|||
mkdir -p -v \"${line}\" || true
|
||||
fi
|
||||
done < #{remote_fn}'
|
||||
") do |type, data|
|
||||
", sudo: opts[:sudo] || false) do |type, data|
|
||||
if type == :stdout && /^.*\'(?<dir>.*)\'/ =~ data
|
||||
created_paths << dir.strip
|
||||
end
|
||||
|
|
|
@ -44,7 +44,7 @@ module VagrantPlugins
|
|||
"rm -f '#{compressed_file}'",
|
||||
"rm -rf '#{extract_dir}'"
|
||||
]
|
||||
cmds.each{ |cmd| comm.execute(cmd) }
|
||||
cmds.each{ |cmd| comm.execute(cmd, sudo: opts[:sudo] || false) }
|
||||
true
|
||||
end
|
||||
|
||||
|
@ -68,7 +68,7 @@ module VagrantPlugins
|
|||
"rm -f '#{compressed_file}'",
|
||||
"rm -rf '#{extract_dir}'"
|
||||
]
|
||||
cmds.each{ |cmd| comm.execute(cmd) }
|
||||
cmds.each{ |cmd| comm.execute(cmd, sudo: opts[:sudo] || false) }
|
||||
true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -66,7 +66,7 @@ module VagrantPlugins
|
|||
#
|
||||
# @param [Vagrant::Machine] machine Vagrant guest machine
|
||||
# @param [array] paths to create on guest
|
||||
def self.create_directories(machine, dirs)
|
||||
def self.create_directories(machine, dirs, opts={})
|
||||
return [] if dirs.empty?
|
||||
|
||||
remote_fn = create_tmp_path(machine, {})
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
require 'find'
|
||||
|
||||
require_relative '../helper'
|
||||
|
||||
module VagrantPlugins
|
||||
module HyperV
|
||||
module Cap
|
||||
module SyncFolder
|
||||
def self.sync_folder(machine, data)
|
||||
is_win_guest = machine.guest.name == :windows
|
||||
host_path = VagrantPlugins::HyperV::SyncHelper.expand_path(data[:hostpath])
|
||||
guest_path = data[:guestpath]
|
||||
win_host_path = Vagrant::Util::Platform.windows_path(
|
||||
host_path, :disable_unc)
|
||||
win_guest_path = guest_path.tr '/', '\\'
|
||||
|
||||
includes = find_includes(data[:hostpath], data[:exclude])
|
||||
dir_mappings = {}
|
||||
file_mappings = {}
|
||||
platform_guest_path = is_win_guest ? win_guest_path : guest_path
|
||||
{ dirs: dir_mappings,
|
||||
files: file_mappings }.map do |sym, mapping|
|
||||
includes[sym].map do |e|
|
||||
guest_rel = e.gsub(host_path, '')
|
||||
guest_rel = guest_rel[1..-1] if guest_rel.start_with? '\\', '/'
|
||||
guest_rel.tr! '\\', '/'
|
||||
|
||||
# make sure the dir names are Windows-style for them to pass to Hyper-V
|
||||
if guest_rel == ''
|
||||
win_path = win_host_path
|
||||
target = platform_guest_path
|
||||
else
|
||||
win_path = HyperV::SyncHelper.platform_join(win_host_path, guest_rel)
|
||||
guest_rel = guest_rel.split("/")[0..-2].join("/") if sym == :files
|
||||
target = HyperV::SyncHelper.platform_join(platform_guest_path, guest_rel,
|
||||
is_windows: is_win_guest)
|
||||
target = target[0..-2] if target.end_with? '\\', '/'
|
||||
end
|
||||
mapping[win_path] = target
|
||||
end
|
||||
end
|
||||
machine.guest.capability(:create_directories, dir_mappings.values)
|
||||
machine.provider.driver.sync_files(machine.id, dir_mappings, file_mappings,
|
||||
is_win_guest: is_win_guest)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def self.find_includes(path, exclude)
|
||||
expanded_path = HyperV::SyncHelper.expand_path(path)
|
||||
excludes = HyperV::SyncHelper.expand_excludes(path, exclude)
|
||||
included_dirs = []
|
||||
included_files = []
|
||||
Find.find(expanded_path) do |e|
|
||||
if VagrantPlugins::HyperV::SyncHelper.directory?(e)
|
||||
path = File.join e, ''
|
||||
next if excludes[:dirs].include? path
|
||||
next if excludes[:dirs].select { |x| path.start_with? x }.any?
|
||||
|
||||
included_dirs << e
|
||||
else
|
||||
next if excludes[:files].include? e
|
||||
next if excludes[:dirs].select { |x| e.start_with? x }.any?
|
||||
|
||||
included_files << e
|
||||
end
|
||||
end
|
||||
{ dirs: included_dirs,
|
||||
files: included_files }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,6 +6,11 @@ module VagrantPlugins
|
|||
WINDOWS_SEPARATOR = "\\"
|
||||
UNIX_SEPARATOR = "/"
|
||||
|
||||
# Expands glob-style exclude string
|
||||
#
|
||||
# @param [String] path Path to operate on
|
||||
# @param [String] exclude Array of glob-style exclude strings
|
||||
# @return [Hash] Excluded directories and files
|
||||
def self.expand_excludes(path, exclude)
|
||||
excludes = ['.vagrant/']
|
||||
excludes += Array(exclude).map(&:to_s) if exclude
|
||||
|
@ -29,21 +34,272 @@ module VagrantPlugins
|
|||
files: excluded_files}
|
||||
end
|
||||
|
||||
def self.find_includes(path, exclude)
|
||||
expanded_path = expand_path(path)
|
||||
excludes = expand_excludes(path, exclude)
|
||||
included_dirs = []
|
||||
included_files = []
|
||||
Find.find(expanded_path) do |e|
|
||||
if directory?(e)
|
||||
path = File.join e, ''
|
||||
next if excludes[:dirs].include? path
|
||||
next if excludes[:dirs].select { |x| path.start_with? x }.any?
|
||||
|
||||
included_dirs << e
|
||||
else
|
||||
next if excludes[:files].include? e
|
||||
next if excludes[:dirs].select { |x| e.start_with? x }.any?
|
||||
|
||||
included_files << e
|
||||
end
|
||||
end
|
||||
{ dirs: included_dirs,
|
||||
files: included_files }
|
||||
end
|
||||
|
||||
def self.path_mapping(host_path, guest_path, includes, is_win_guest:)
|
||||
host_path = expand_path(host_path)
|
||||
platform_host_path = platform_path host_path, is_windows: !Vagrant::Util::Platform.wsl?
|
||||
win_host_path = Vagrant::Util::Platform.windows_path(host_path, :disable_unc)
|
||||
platform_guest_path = platform_path(guest_path, is_windows: is_win_guest)
|
||||
|
||||
dir_mappings = { hyperv: {}, platform: {} }
|
||||
file_mappings = { hyperv: {}, platform: {} }
|
||||
{ dirs: dir_mappings,
|
||||
files: file_mappings }.map do |sym, mapping|
|
||||
includes[sym].map do |e|
|
||||
guest_rel = e.gsub(host_path, '')
|
||||
guest_rel = trim_head guest_rel
|
||||
guest_rel = to_unix_path guest_rel
|
||||
|
||||
if guest_rel == ''
|
||||
file_host_path = win_host_path
|
||||
file_platform_host_path = platform_host_path
|
||||
target = platform_guest_path
|
||||
else
|
||||
file_host_path = platform_join(win_host_path, guest_rel)
|
||||
file_platform_host_path = platform_join(platform_host_path, guest_rel,
|
||||
is_windows: !Vagrant::Util::Platform.wsl?)
|
||||
guest_rel = guest_rel.split(UNIX_SEPARATOR)[0..-2].join(UNIX_SEPARATOR) if sym == :files
|
||||
target = platform_join(platform_guest_path, guest_rel, is_windows: is_win_guest)
|
||||
target = trim_tail target
|
||||
end
|
||||
# make sure the dir names are Windows-style for them to pass to Hyper-V
|
||||
mapping[:hyperv][file_host_path] = target
|
||||
mapping[:platform][file_platform_host_path] = target
|
||||
end
|
||||
end
|
||||
{ dirs: dir_mappings, files: file_mappings }
|
||||
end
|
||||
|
||||
# Syncs single folder to guest machine
|
||||
#
|
||||
# @param [Vagrant::Machine] path Path to operate on
|
||||
# @param [Hash] ssh_info
|
||||
# @param [Hash] opts Synced folder details
|
||||
def self.sync_single(machine, ssh_info, opts)
|
||||
is_win_guest = machine.guest.name == :windows
|
||||
host_path = opts[:hostpath]
|
||||
guest_path = opts[:guestpath]
|
||||
|
||||
includes = find_includes(host_path, opts[:exclude])
|
||||
if opts[:no_compression]
|
||||
# Copy file to guest directly for disk consumption saving
|
||||
guest_path_mapping = path_mapping(host_path, guest_path, includes, is_win_guest: is_win_guest)
|
||||
remove_directory machine, guest_path, is_win_guest: is_win_guest, sudo: true
|
||||
machine.guest.capability(:create_directories, guest_path_mapping[:dirs][:hyperv].values, sudo: true)
|
||||
if hyperv_copy? machine
|
||||
machine.provider.driver.sync_files(machine.id,
|
||||
guest_path_mapping[:dirs][:hyperv],
|
||||
guest_path_mapping[:files][:hyperv],
|
||||
is_win_guest: is_win_guest)
|
||||
else
|
||||
guest_path_mapping[:files][:platform].each do |host_path, guest_path|
|
||||
next unless file_exist? host_path
|
||||
|
||||
stat = file_stat host_path
|
||||
next if stat.symlink?
|
||||
|
||||
machine.communicate.upload(host_path, guest_path)
|
||||
end
|
||||
end
|
||||
else
|
||||
source_items = includes[:files]
|
||||
type = is_win_guest ? :zip : :tgz
|
||||
host_path = expand_path(host_path)
|
||||
source = send("compress_source_#{type}".to_sym, host_path, source_items)
|
||||
decompress_cap = type == :zip ? :decompress_zip : :decompress_tgz
|
||||
begin
|
||||
destination = machine.guest.capability(:create_tmp_path, extension: ".#{type}")
|
||||
upload_file(machine, source, destination, is_win_guest: is_win_guest)
|
||||
remove_directory machine, guest_path, is_win_guest: is_win_guest, sudo: true
|
||||
machine.guest.capability(decompress_cap, destination, platform_path(guest_path, is_windows: is_win_guest),
|
||||
type: :directory, sudo: true)
|
||||
ensure
|
||||
FileUtils.rm_f source if file_exist? source
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Compress path using zip into temporary file
|
||||
#
|
||||
# @param [String] path Path to compress
|
||||
# @return [String] path to compressed file
|
||||
def self.compress_source_zip(path, source_items)
|
||||
require "zip"
|
||||
zipfile = Tempfile.create(%w(vagrant .zip), format_windows_temp)
|
||||
zipfile.close
|
||||
c_dir = nil
|
||||
Zip::File.open(zipfile.path, Zip::File::CREATE) do |zip|
|
||||
source_items.each do |source_item|
|
||||
next unless file_exist? source_item
|
||||
next if directory?(source_item)
|
||||
|
||||
stat = file_stat(source_item)
|
||||
next if stat.symlink?
|
||||
|
||||
trim_item = source_item.sub(path, "").sub(%r{^[/\\]}, "")
|
||||
dirname = File.dirname(trim_item)
|
||||
begin
|
||||
zip.get_entry(dirname)
|
||||
rescue Errno::ENOENT
|
||||
zip.mkdir dirname if c_dir != dirname
|
||||
end
|
||||
c_dir = dirname
|
||||
zip.get_output_stream(trim_item) do |f|
|
||||
source_file = File.open(source_item, "rb")
|
||||
while data = source_file.read(2048)
|
||||
f.write(data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
zipfile.path
|
||||
end
|
||||
|
||||
# Compress path using tar and gzip into temporary file
|
||||
#
|
||||
# @param [String] path Path to compress
|
||||
# @return [String] path to compressed file
|
||||
def self.compress_source_tgz(path, source_items)
|
||||
tmp_dir = format_windows_temp
|
||||
tarfile = Tempfile.create(%w(vagrant .tar), tmp_dir)
|
||||
tarfile.close
|
||||
tarfile = File.open(tarfile.path, "wb+")
|
||||
tgzfile = Tempfile.create(%w(vagrant .tgz), tmp_dir)
|
||||
tgzfile.close
|
||||
tgzfile = File.open(tgzfile.path, "wb")
|
||||
tar = Gem::Package::TarWriter.new(tarfile)
|
||||
tgz = Zlib::GzipWriter.new(tgzfile)
|
||||
source_items.each do |item|
|
||||
next unless file_exist? item
|
||||
|
||||
rel_path = item.sub(path, "")
|
||||
stat = file_stat(item)
|
||||
item_mode = stat.mode
|
||||
|
||||
if directory?(item)
|
||||
tar.mkdir(rel_path, item_mode)
|
||||
elsif stat.symlink?
|
||||
tar.add_symlink(rel_path, File.readlink(item), item_mode)
|
||||
else
|
||||
tar.add_file(rel_path, item_mode) do |io|
|
||||
File.open(item, "rb") do |file|
|
||||
while bytes = file.read(4096)
|
||||
io.write(bytes)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
tar.close
|
||||
tarfile.rewind
|
||||
while bytes = tarfile.read(4096)
|
||||
tgz.write bytes
|
||||
end
|
||||
tgz.close
|
||||
tgzfile.close
|
||||
tarfile.close
|
||||
File.delete(tarfile.path)
|
||||
tgzfile.path
|
||||
end
|
||||
|
||||
def self.remove_directory(machine, guestpath, is_win_guest: false, sudo: false)
|
||||
comm = machine.communicate
|
||||
if is_win_guest
|
||||
guestpath = to_windows_path guestpath
|
||||
cmd = <<-EOH.gsub(/^ {6}/, "")
|
||||
if (Test-Path(\"#{guestpath}\")) {
|
||||
Remove-Item -Path \"#{guestpath}\" -Recurse -Force
|
||||
}
|
||||
EOH
|
||||
comm.execute(cmd, shell: :powershell)
|
||||
else
|
||||
guestpath = to_unix_path guestpath
|
||||
if comm.test("test -d '#{guestpath}'")
|
||||
comm.execute("rm -rf '#{guestpath}'", sudo: sudo)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.format_windows_temp
|
||||
windows_temp = Vagrant::Util::Platform.windows_temp
|
||||
if Vagrant::Util::Platform.wsl?
|
||||
process = Vagrant::Util::Subprocess.execute(
|
||||
"wslpath", "-u", "-a", windows_temp)
|
||||
windows_temp = process.stdout.chomp if process.exit_code == 0
|
||||
end
|
||||
windows_temp
|
||||
end
|
||||
|
||||
def self.upload_file(machine, source, dest, is_win_guest:)
|
||||
begin
|
||||
# try Hyper-V guest integration service first as WinRM upload is slower
|
||||
if hyperv_copy? machine
|
||||
separator = is_win_guest ? WINDOWS_SEPARATOR: UNIX_SEPARATOR
|
||||
parts = dest.split(separator)
|
||||
filename = parts[-1]
|
||||
dest_dir = parts[0..-2].join(separator)
|
||||
|
||||
windows_temp = format_windows_temp
|
||||
source_copy = platform_join windows_temp, filename, is_windows: !Vagrant::Util::Platform.wsl?
|
||||
FileUtils.mv source, source_copy
|
||||
source = source_copy
|
||||
hyperv_copy machine, source, dest_dir
|
||||
else
|
||||
machine.communicate.upload(source, dest)
|
||||
end
|
||||
ensure
|
||||
FileUtils.rm_f source
|
||||
end
|
||||
end
|
||||
|
||||
def self.hyperv_copy?(machine)
|
||||
machine.guest.capability?(:hyperv_daemons_running) && machine.guest.capability(:hyperv_daemons_running)
|
||||
end
|
||||
|
||||
def self.hyperv_copy(machine, source, dest_dir)
|
||||
vm_id = machine.id
|
||||
ps_cmd = <<-EOH.gsub(/^ {6}/, "")
|
||||
$machine = Hyper-V\\Get-VM -Id \"#{vm_id}\"
|
||||
Hyper-V\\Copy-VMFile -VM $machine -SourcePath \"#{source}\" -DestinationPath \"#{dest_dir}\" -CreateFullPath -FileSource Host -Force
|
||||
EOH
|
||||
Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
|
||||
end
|
||||
|
||||
def self.platform_join(string, *smth, is_windows: true)
|
||||
joined = [string, *smth].join is_windows ? WINDOWS_SEPARATOR : UNIX_SEPARATOR
|
||||
if is_windows
|
||||
joined.tr! UNIX_SEPARATOR, WINDOWS_SEPARATOR
|
||||
to_windows_path joined
|
||||
else
|
||||
joined.tr! WINDOWS_SEPARATOR, UNIX_SEPARATOR
|
||||
to_unix_path joined
|
||||
end
|
||||
joined
|
||||
end
|
||||
|
||||
def self.sync_single(machine, ssh_info, opts)
|
||||
opts = opts.dup
|
||||
opts[:owner] ||= ssh_info[:username]
|
||||
opts[:group] ||= ssh_info[:username]
|
||||
machine.provider.capability(:sync_folder, opts)
|
||||
def self.platform_path(path, is_windows: true)
|
||||
win_path = to_windows_path path
|
||||
linux_path = to_unix_path path
|
||||
is_windows ? win_path : linux_path
|
||||
end
|
||||
|
||||
def self.expand_path(*path)
|
||||
|
@ -55,6 +311,32 @@ module VagrantPlugins
|
|||
# stub for unit test
|
||||
File.directory? path
|
||||
end
|
||||
|
||||
def self.file_exist?(path)
|
||||
# stub for unit test
|
||||
File.exist? path
|
||||
end
|
||||
|
||||
def self.file_stat(path)
|
||||
# stub for unit test
|
||||
File.stat path
|
||||
end
|
||||
|
||||
def self.to_windows_path(path)
|
||||
path.tr UNIX_SEPARATOR, WINDOWS_SEPARATOR
|
||||
end
|
||||
|
||||
def self.to_unix_path(path)
|
||||
path.tr WINDOWS_SEPARATOR, UNIX_SEPARATOR
|
||||
end
|
||||
|
||||
def self.trim_head(path)
|
||||
path.start_with?(WINDOWS_SEPARATOR, UNIX_SEPARATOR) ? path[1..-1] : path
|
||||
end
|
||||
|
||||
def self.trim_tail(path)
|
||||
path.end_with?(WINDOWS_SEPARATOR, UNIX_SEPARATOR) ? path[0..-2] : path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,11 +27,6 @@ module VagrantPlugins
|
|||
Config
|
||||
end
|
||||
|
||||
provider_capability("hyperv", "sync_folder") do
|
||||
require_relative "cap/sync_folder"
|
||||
Cap::SyncFolder
|
||||
end
|
||||
|
||||
provider_capability("hyperv", "public_address") do
|
||||
require_relative "cap/public_address"
|
||||
Cap::PublicAddress
|
||||
|
|
|
@ -45,40 +45,45 @@ describe "VagrantPlugins::GuestBSD::Cap::FileSystem" do
|
|||
let(:cap) { caps.get(:decompress_tgz) }
|
||||
let(:comp) { "compressed_file" }
|
||||
let(:dest) { "path/to/destination" }
|
||||
let(:opts) { {} }
|
||||
|
||||
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
|
||||
after{ cap.decompress_tgz(machine, comp, dest, opts) }
|
||||
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
[false, true].each do |sudo_flag|
|
||||
context "sudo flag: #{sudo_flag}" do
|
||||
let(:opts) { {sudo: sudo_flag} }
|
||||
|
||||
it "should extract file with tar" do
|
||||
expect(comm).to receive(:execute).with(/tar/)
|
||||
end
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/)
|
||||
end
|
||||
it "should extract file with tar" do
|
||||
expect(comm).to receive(:execute).with(/tar/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
|
||||
end
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
|
||||
end
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
|
||||
end
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/, sudo: sudo_flag)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -87,40 +92,45 @@ describe "VagrantPlugins::GuestBSD::Cap::FileSystem" do
|
|||
let(:cap) { caps.get(:decompress_zip) }
|
||||
let(:comp) { "compressed_file" }
|
||||
let(:dest) { "path/to/destination" }
|
||||
let(:opts) { {} }
|
||||
|
||||
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
|
||||
after{ cap.decompress_zip(machine, comp, dest, opts) }
|
||||
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
[false, true].each do |sudo_flag|
|
||||
context "sudo flag: #{sudo_flag}" do
|
||||
let(:opts) { {sudo: sudo_flag} }
|
||||
|
||||
it "should extract file with zip" do
|
||||
expect(comm).to receive(:execute).with(/zip/)
|
||||
end
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/)
|
||||
end
|
||||
it "should extract file with zip" do
|
||||
expect(comm).to receive(:execute).with(/zip/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
|
||||
end
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
|
||||
end
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
|
||||
end
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/, sudo: sudo_flag)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -45,40 +45,45 @@ describe "VagrantPlugins::GuestLinux::Cap::FileSystem" do
|
|||
let(:cap) { caps.get(:decompress_tgz) }
|
||||
let(:comp) { "compressed_file" }
|
||||
let(:dest) { "path/to/destination" }
|
||||
let(:opts) { {} }
|
||||
|
||||
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
|
||||
after{ cap.decompress_tgz(machine, comp, dest, opts) }
|
||||
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
[false, true].each do |sudo_flag|
|
||||
context "sudo flag: #{sudo_flag}" do
|
||||
let(:opts) { {sudo: sudo_flag} }
|
||||
|
||||
it "should extract file with tar" do
|
||||
expect(comm).to receive(:execute).with(/tar/)
|
||||
end
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/)
|
||||
end
|
||||
it "should extract file with tar" do
|
||||
expect(comm).to receive(:execute).with(/tar/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
|
||||
end
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
|
||||
end
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
|
||||
end
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/, sudo: sudo_flag)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -87,40 +92,45 @@ describe "VagrantPlugins::GuestLinux::Cap::FileSystem" do
|
|||
let(:cap) { caps.get(:decompress_zip) }
|
||||
let(:comp) { "compressed_file" }
|
||||
let(:dest) { "path/to/destination" }
|
||||
let(:opts) { {} }
|
||||
|
||||
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
|
||||
after{ cap.decompress_zip(machine, comp, dest, opts) }
|
||||
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
[false, true].each do |sudo_flag|
|
||||
context "sudo flag: #{sudo_flag}" do
|
||||
let(:opts) { {sudo: sudo_flag} }
|
||||
|
||||
it "should extract file with zip" do
|
||||
expect(comm).to receive(:execute).with(/zip/)
|
||||
end
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/)
|
||||
end
|
||||
it "should extract file with zip" do
|
||||
expect(comm).to receive(:execute).with(/zip/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
|
||||
end
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
|
||||
end
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
|
||||
end
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/, sudo: sudo_flag)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -130,66 +140,73 @@ describe "VagrantPlugins::GuestLinux::Cap::FileSystem" do
|
|||
let(:dirs) { %w(dir1 dir2) }
|
||||
|
||||
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
|
||||
after { expect(cap.create_directories(machine, dirs)).to eql(dirs) }
|
||||
|
||||
context "passes directories to be create" do
|
||||
let(:temp_file) do
|
||||
double("temp_file").tap do |temp_file|
|
||||
allow(temp_file).to receive(:binmode)
|
||||
allow(temp_file).to receive(:close)
|
||||
allow(temp_file).to receive(:path).and_return("temp_path")
|
||||
allow(temp_file).to receive(:unlink)
|
||||
end
|
||||
end
|
||||
let(:sudo_block) do
|
||||
Proc.new do |arg, &proc|
|
||||
lines = arg.split("\n")
|
||||
expect(lines[lines.length - 2]).to match(/TMP_DIR/)
|
||||
dirs.each do |dir|
|
||||
proc.call :stdout, "mkdir: created directory '#{dir}'\n"
|
||||
[false, true].each do |sudo_flag|
|
||||
context "sudo flag: #{sudo_flag}" do
|
||||
let(:opts) { {sudo: sudo_flag} }
|
||||
|
||||
after { expect(cap.create_directories(machine, dirs, opts)).to eql(dirs) }
|
||||
|
||||
context "passes directories to be create" do
|
||||
let(:temp_file) do
|
||||
double("temp_file").tap do |temp_file|
|
||||
allow(temp_file).to receive(:binmode)
|
||||
allow(temp_file).to receive(:close)
|
||||
allow(temp_file).to receive(:path).and_return("temp_path")
|
||||
allow(temp_file).to receive(:unlink)
|
||||
end
|
||||
end
|
||||
let(:exec_block) do
|
||||
Proc.new do |arg, &proc|
|
||||
lines = arg.split("\n")
|
||||
expect(lines[lines.length - 2]).to match(/TMP_DIR/)
|
||||
dirs.each do |dir|
|
||||
proc.call :stdout, "mkdir: created directory '#{dir}'\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Tempfile).to receive(:new).and_return(temp_file)
|
||||
allow(temp_file).to receive(:write)
|
||||
allow(temp_file).to receive(:close)
|
||||
allow(comm).to receive(:upload)
|
||||
allow(comm).to receive(:execute, &exec_block)
|
||||
end
|
||||
|
||||
it "creates temporary file on guest" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
|
||||
it "creates a temporary file to write dir list" do
|
||||
expect(Tempfile).to receive(:new).and_return(temp_file)
|
||||
end
|
||||
|
||||
it "writes dir list to a local temporary file" do
|
||||
expect(temp_file).to receive(:write).with(dirs.join("\n") + "\n")
|
||||
end
|
||||
|
||||
it "uploads the local temporary file with dir list to guest" do
|
||||
expect(comm).to receive(:upload).with("temp_path", "TMP_DIR")
|
||||
end
|
||||
|
||||
it "executes bash script to create directories on guest" do
|
||||
expect(comm).to receive(:execute, &exec_block).with(/bash -c .*/, sudo: sudo_flag)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Tempfile).to receive(:new).and_return(temp_file)
|
||||
allow(temp_file).to receive(:write)
|
||||
allow(temp_file).to receive(:close)
|
||||
allow(comm).to receive(:upload)
|
||||
allow(comm).to receive(:sudo, &sudo_block)
|
||||
end
|
||||
context "passes empty dir list" do
|
||||
let(:dirs) { [] }
|
||||
|
||||
it "creates temporary file on guest" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
after { expect(cap.create_directories(machine, dirs, opts)).to eql([]) }
|
||||
|
||||
it "creates a temporary file to write dir list" do
|
||||
expect(Tempfile).to receive(:new).and_return(temp_file)
|
||||
end
|
||||
|
||||
it "writes dir list to a local temporary file" do
|
||||
expect(temp_file).to receive(:write).with(dirs.join("\n") + "\n")
|
||||
end
|
||||
|
||||
it "uploads the local temporary file with dir list to guest" do
|
||||
expect(comm).to receive(:upload).with("temp_path", "TMP_DIR")
|
||||
end
|
||||
|
||||
it "executes bash script to create directories on guest" do
|
||||
expect(comm).to receive(:sudo, &sudo_block)
|
||||
end
|
||||
end
|
||||
|
||||
context "passes empty dir list" do
|
||||
let(:dirs) { [] }
|
||||
|
||||
after { expect(cap.create_directories(machine, dirs)).to eql([]) }
|
||||
|
||||
it "does nothing" do
|
||||
expect(cap).to receive(:create_tmp_path).never
|
||||
expect(Tempfile).to receive(:new).never
|
||||
expect(comm).to receive(:upload).never
|
||||
expect(comm).to receive(:sudo).never
|
||||
it "does nothing" do
|
||||
expect(cap).to receive(:create_tmp_path).never
|
||||
expect(Tempfile).to receive(:new).never
|
||||
expect(comm).to receive(:upload).never
|
||||
expect(comm).to receive(:execute).never
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -45,40 +45,45 @@ describe "VagrantPlugins::GuestSolaris::Cap::FileSystem" do
|
|||
let(:cap) { caps.get(:decompress_tgz) }
|
||||
let(:comp) { "compressed_file" }
|
||||
let(:dest) { "path/to/destination" }
|
||||
let(:opts) { {} }
|
||||
|
||||
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
|
||||
after{ cap.decompress_tgz(machine, comp, dest, opts) }
|
||||
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
[false, true].each do |sudo_flag|
|
||||
context "sudo flag: #{sudo_flag}" do
|
||||
let(:opts) { {sudo: sudo_flag} }
|
||||
|
||||
it "should extract file with tar" do
|
||||
expect(comm).to receive(:execute).with(/tar/)
|
||||
end
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/)
|
||||
end
|
||||
it "should extract file with tar" do
|
||||
expect(comm).to receive(:execute).with(/tar/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
|
||||
end
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
|
||||
end
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
|
||||
end
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/, sudo: sudo_flag)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -87,40 +92,45 @@ describe "VagrantPlugins::GuestSolaris::Cap::FileSystem" do
|
|||
let(:cap) { caps.get(:decompress_zip) }
|
||||
let(:comp) { "compressed_file" }
|
||||
let(:dest) { "path/to/destination" }
|
||||
let(:opts) { {} }
|
||||
|
||||
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
|
||||
after{ cap.decompress_zip(machine, comp, dest, opts) }
|
||||
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
[false, true].each do |sudo_flag|
|
||||
context "sudo flag: #{sudo_flag}" do
|
||||
let(:opts) { {sudo: sudo_flag} }
|
||||
|
||||
it "should extract file with zip" do
|
||||
expect(comm).to receive(:execute).with(/zip/)
|
||||
end
|
||||
it "should create temporary directory for extraction" do
|
||||
expect(cap).to receive(:create_tmp_path)
|
||||
end
|
||||
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/)
|
||||
end
|
||||
it "should extract file with zip" do
|
||||
expect(comm).to receive(:execute).with(/zip/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
|
||||
end
|
||||
it "should extract file to temporary directory" do
|
||||
expect(comm).to receive(:execute).with(/TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
|
||||
end
|
||||
it "should remove compressed file from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*#{comp}/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
|
||||
end
|
||||
it "should remove extraction directory from guest" do
|
||||
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
it "should create parent directories for destination" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*to'/, sudo: sudo_flag)
|
||||
end
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
|
||||
context "when type is directory" do
|
||||
before { opts[:type] = :directory }
|
||||
|
||||
it "should create destination directory" do
|
||||
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/, sudo: sudo_flag)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,260 +0,0 @@
|
|||
require_relative "../../../../base"
|
||||
|
||||
require Vagrant.source_root.join("plugins/providers/hyperv/cap/sync_folder")
|
||||
|
||||
describe VagrantPlugins::HyperV::Cap::SyncFolder do
|
||||
include_context "unit"
|
||||
|
||||
let(:iso_env) do
|
||||
# We have to create a Vagrantfile so there is a root path
|
||||
env = isolated_environment
|
||||
env.vagrantfile("")
|
||||
env.create_vagrant_env
|
||||
end
|
||||
|
||||
let(:guest) { double("guest") }
|
||||
let(:driver) { double("driver") }
|
||||
let(:provider) do
|
||||
double("provider").tap do |provider|
|
||||
allow(provider).to receive(:driver).and_return(driver)
|
||||
end
|
||||
end
|
||||
let(:vm_id) { 'vm_id' }
|
||||
let(:machine) do
|
||||
iso_env.machine(iso_env.machine_names[0], :dummy).tap do |m|
|
||||
allow(m).to receive(:guest).and_return(guest)
|
||||
allow(m).to receive(:provider).and_return(provider)
|
||||
allow(m).to receive(:id).and_return(vm_id)
|
||||
end
|
||||
end
|
||||
let(:hostpath) { 'vagrant' }
|
||||
let(:exclude) { [".git/"] }
|
||||
let(:expanded_hostpaths) do
|
||||
{ Windows: 'C:\vagrant', WSL: "/vagrant" }
|
||||
end
|
||||
let(:guestpaths) do
|
||||
{ windows: 'C:\vagrant', linux: "/vagrant" }
|
||||
end
|
||||
let(:paths) do
|
||||
{ Windows: %w[C:\vagrant C:\vagrant\.vagrant C:\vagrant\.git C:\vagrant\test],
|
||||
WSL: %w[/vagrant /vagrant/.vagrant /vagrant/.git /vagrant/test] }
|
||||
end
|
||||
let(:separators) do
|
||||
{ Windows: '\\', WSL: "/" }
|
||||
end
|
||||
let(:shared_folder) do
|
||||
{ hostpath: 'vagrant',
|
||||
owner: "vagrant",
|
||||
group: "vagrant",
|
||||
exclude: [".git/"] }
|
||||
end
|
||||
|
||||
def random_name
|
||||
(0...8).map { ('a'..'z').to_a[rand(26)] }.join
|
||||
end
|
||||
|
||||
def generate_random_file(files, path, separator, is_directory: true)
|
||||
prefix = is_directory ? "dir" : "file"
|
||||
fn = [path, "#{prefix}_#{random_name}"].join(separator)
|
||||
files << fn
|
||||
allow(VagrantPlugins::HyperV::SyncHelper).to receive(:directory?).with(fn).and_return(is_directory)
|
||||
fn
|
||||
end
|
||||
|
||||
def generate_test_data(paths, separator)
|
||||
files = []
|
||||
excludes = { dirs: [], files: [] }
|
||||
includes = { dirs: [], files: [] }
|
||||
paths.map do |dir|
|
||||
files << dir
|
||||
excluded = dir.end_with?('.vagrant', '.git')
|
||||
allow(VagrantPlugins::HyperV::SyncHelper).to receive(:directory?).with(dir).and_return(true)
|
||||
(0..10).map do
|
||||
fn = generate_random_file(files, dir, separator, is_directory: false)
|
||||
if excluded
|
||||
excludes[:files] << fn
|
||||
else
|
||||
includes[:files] << fn
|
||||
end
|
||||
end
|
||||
|
||||
sub_dir = generate_random_file(files, dir, separator, is_directory: true)
|
||||
if excluded
|
||||
excludes[:dirs] << dir
|
||||
excludes[:dirs] << sub_dir
|
||||
else
|
||||
includes[:dirs] << dir
|
||||
includes[:dirs] << sub_dir
|
||||
end
|
||||
|
||||
(0..10).map do
|
||||
fn = generate_random_file(files, sub_dir, separator, is_directory: false)
|
||||
if excluded
|
||||
excludes[:files] << fn
|
||||
else
|
||||
includes[:files] << fn
|
||||
end
|
||||
end
|
||||
end
|
||||
{ files: files,
|
||||
excludes: excludes,
|
||||
includes: includes }
|
||||
end
|
||||
|
||||
def convert_path(mapping, path, host_type, guest_type, is_file: true)
|
||||
win_path = path.gsub "/vagrant", 'C:\vagrant'
|
||||
win_path.tr! "/", '\\'
|
||||
|
||||
linux_path = path.gsub 'C:\vagrant', "/vagrant"
|
||||
linux_path.tr! '\\', "/"
|
||||
|
||||
dir_win_path = is_file ? win_path.split("\\")[0..-2].join("\\") : win_path
|
||||
dir_win_path = dir_win_path[0..-2] if dir_win_path.end_with? '\\', '/'
|
||||
|
||||
dir_linux_path = is_file ? linux_path.split("/")[0..-2].join("/") : linux_path
|
||||
dir_linux_path = dir_linux_path[0..-2] if dir_linux_path.end_with? '\\', '/'
|
||||
|
||||
mapping[win_path] =
|
||||
if host_type == :WSL
|
||||
if guest_type == :linux
|
||||
dir_linux_path
|
||||
else
|
||||
dir_win_path
|
||||
end
|
||||
else
|
||||
# windows
|
||||
if guest_type == :linux
|
||||
dir_linux_path
|
||||
else
|
||||
dir_win_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#sync_folder" do
|
||||
%i[windows linux].map do |guest_type|
|
||||
context "syncs folders to #{guest_type} guest" do
|
||||
%i[Windows WSL].map do |host_type|
|
||||
context "in #{host_type} environment" do
|
||||
let(:host_type) { host_type }
|
||||
let(:guest_type) { guest_type }
|
||||
let(:separator) { separators[host_type] }
|
||||
let(:input_paths) { paths[host_type] }
|
||||
let(:expanded_hostpath) { expanded_hostpaths[host_type] }
|
||||
let(:expanded_hostpath_windows) { expanded_hostpaths[:Windows] }
|
||||
let(:guestpath) { guestpaths[guest_type] }
|
||||
let(:test_data) { generate_test_data input_paths, separator }
|
||||
let(:includes) { test_data[:includes] }
|
||||
let(:dir_mappings) do
|
||||
mappings = {}
|
||||
includes[:dirs].map do |dir|
|
||||
convert_path(mappings, dir, host_type, guest_type, is_file: false)
|
||||
end
|
||||
mappings
|
||||
end
|
||||
let(:files_mappings) do
|
||||
mappings = {}
|
||||
includes[:files].map do |file|
|
||||
convert_path(mappings, file, host_type, guest_type, is_file: true)
|
||||
end
|
||||
mappings
|
||||
end
|
||||
let(:opts) do
|
||||
shared_folder.dup.tap do |opts|
|
||||
opts[:guestpath] = guestpath
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
allow(guest).to receive(:name).and_return(guest_type)
|
||||
allow(VagrantPlugins::HyperV::SyncHelper).to receive(:expand_path).
|
||||
with(hostpath).and_return(expanded_hostpath)
|
||||
allow(Vagrant::Util::Platform).to receive(:windows_path).
|
||||
with(expanded_hostpath, :disable_unc).and_return(expanded_hostpath_windows)
|
||||
allow(described_class).to receive(:find_includes).
|
||||
with(hostpath, exclude).and_return(includes)
|
||||
allow(guest).to receive(:capability).with(:create_directories, dir_mappings.values)
|
||||
allow(driver).to receive(:sync_files).
|
||||
with(vm_id, dir_mappings, files_mappings, is_win_guest: guest_type == :windows)
|
||||
end
|
||||
|
||||
after { expect(described_class.sync_folder(machine, opts)) }
|
||||
|
||||
it "expands host path to full path" do
|
||||
expect(VagrantPlugins::HyperV::SyncHelper).to receive(:expand_path).
|
||||
with(hostpath).and_return(expanded_hostpath)
|
||||
end
|
||||
|
||||
it "formats expanded full path to windows path" do
|
||||
expect(Vagrant::Util::Platform).to receive(:windows_path).
|
||||
with(expanded_hostpath, :disable_unc).and_return(expanded_hostpath_windows)
|
||||
end
|
||||
|
||||
it "finds all files included in transfer" do
|
||||
expect(described_class).to receive(:find_includes).
|
||||
with(hostpath, exclude).and_return(includes)
|
||||
end
|
||||
|
||||
it "calls create_directories to make directories" do
|
||||
expect(guest).to receive(:capability).with(:create_directories, dir_mappings.values)
|
||||
end
|
||||
|
||||
it "calls driver #sync_files to sync files" do
|
||||
expect(driver).to receive(:sync_files).
|
||||
with(vm_id, dir_mappings, files_mappings, is_win_guest: guest_type == :windows)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#find_includes" do
|
||||
%i[windows linux].map do |guest_type|
|
||||
context "#{guest_type} guest" do
|
||||
%i[Windows WSL].map do |host_type|
|
||||
context "in #{host_type} environment" do
|
||||
let(:host_type) { host_type }
|
||||
let(:separator) { separators[host_type] }
|
||||
let(:input_paths) { paths[host_type] }
|
||||
let(:expanded_hostpath) { expanded_hostpaths[host_type] }
|
||||
let(:test_data) { generate_test_data input_paths, separator }
|
||||
let(:test_files) { test_data[:files] }
|
||||
let(:test_includes) { test_data[:includes] }
|
||||
let(:test_excludes) { test_data[:excludes] }
|
||||
|
||||
before do
|
||||
allow(VagrantPlugins::HyperV::SyncHelper).to receive(:expand_path).
|
||||
with(hostpath).and_return(expanded_hostpath)
|
||||
allow(VagrantPlugins::HyperV::SyncHelper).to receive(:expand_excludes).
|
||||
with(hostpath, exclude).and_return(test_excludes)
|
||||
allow(Find).to receive(:find).with(expanded_hostpath) do |arg, &proc|
|
||||
test_files.map do |file|
|
||||
proc.call file
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
expect(described_class.send(:find_includes, hostpath, exclude)).to eq(test_includes)
|
||||
end
|
||||
|
||||
it "expands host path to full path" do
|
||||
allow(VagrantPlugins::HyperV::SyncHelper).to receive(:expand_path).
|
||||
with(hostpath).and_return(expanded_hostpath)
|
||||
end
|
||||
|
||||
it "expands excluded files and directories for exclusion" do
|
||||
allow(VagrantPlugins::HyperV::SyncHelper).to receive(:expand_excludes).
|
||||
with(hostpath, exclude).and_return(test_excludes)
|
||||
end
|
||||
|
||||
it "locates all files in expanded host path" do
|
||||
expect(Find).to receive(:find).with(expanded_hostpath)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +1,6 @@
|
|||
require 'find'
|
||||
require 'zip'
|
||||
|
||||
require_relative "../../../base"
|
||||
|
||||
require Vagrant.source_root.join("plugins/providers/hyperv/helper")
|
||||
|
@ -5,6 +8,14 @@ require Vagrant.source_root.join("plugins/providers/hyperv/helper")
|
|||
describe VagrantPlugins::HyperV::SyncHelper do
|
||||
subject { described_class }
|
||||
|
||||
let(:vm_id) { "vm_id" }
|
||||
let(:guest) { double("guest") }
|
||||
let(:comm) { double("comm") }
|
||||
let(:machine) { double("machine", provider: provider, guest: guest, id: vm_id, communicate: comm) }
|
||||
let(:provider) { double("provider", driver: driver) }
|
||||
let(:driver) { double("driver") }
|
||||
let(:separators) { { Windows: '\\', WSL: "/" } }
|
||||
|
||||
def random_name
|
||||
(0...8).map { ('a'..'z').to_a[rand(26)] }.join
|
||||
end
|
||||
|
@ -13,10 +24,82 @@ describe VagrantPlugins::HyperV::SyncHelper do
|
|||
prefix = is_directory ? "dir" : "file"
|
||||
fn = [path, "#{prefix}_#{random_name}"].join(separator)
|
||||
files << fn
|
||||
allow(VagrantPlugins::HyperV::SyncHelper).to receive(:directory?).with(fn).and_return(is_directory)
|
||||
allow(subject).to receive(:directory?).with(fn).and_return(is_directory)
|
||||
fn
|
||||
end
|
||||
|
||||
def generate_test_data(paths, separator)
|
||||
files = []
|
||||
excludes = { dirs: [], files: [] }
|
||||
includes = { dirs: [], files: [] }
|
||||
paths.map do |dir|
|
||||
files << dir
|
||||
excluded = dir.end_with?('.vagrant', '.git')
|
||||
allow(VagrantPlugins::HyperV::SyncHelper).to receive(:directory?).with(dir).and_return(true)
|
||||
(0..10).map do
|
||||
fn = generate_random_file(files, dir, separator, is_directory: false)
|
||||
if excluded
|
||||
excludes[:files] << fn
|
||||
else
|
||||
includes[:files] << fn
|
||||
end
|
||||
end
|
||||
|
||||
sub_dir = generate_random_file(files, dir, separator, is_directory: true)
|
||||
if excluded
|
||||
excludes[:dirs] << dir
|
||||
excludes[:dirs] << sub_dir
|
||||
else
|
||||
includes[:dirs] << dir
|
||||
includes[:dirs] << sub_dir
|
||||
end
|
||||
|
||||
(0..10).map do
|
||||
fn = generate_random_file(files, sub_dir, separator, is_directory: false)
|
||||
if excluded
|
||||
excludes[:files] << fn
|
||||
else
|
||||
includes[:files] << fn
|
||||
end
|
||||
end
|
||||
end
|
||||
{ files: files,
|
||||
excludes: excludes,
|
||||
includes: includes }
|
||||
end
|
||||
|
||||
def convert_path(mapping, path, host_type, guest_type, is_file: true)
|
||||
win_path = path.gsub "/vagrant", 'C:\vagrant'
|
||||
win_path.tr! "/", '\\'
|
||||
|
||||
linux_path = path.gsub 'C:\vagrant', "/vagrant"
|
||||
linux_path.tr! '\\', "/"
|
||||
|
||||
dir_win_path = is_file ? win_path.split("\\")[0..-2].join("\\") : win_path
|
||||
dir_win_path = dir_win_path[0..-2] if dir_win_path.end_with? '\\', '/'
|
||||
|
||||
dir_linux_path = is_file ? linux_path.split("/")[0..-2].join("/") : linux_path
|
||||
dir_linux_path = dir_linux_path[0..-2] if dir_linux_path.end_with? '\\', '/'
|
||||
|
||||
guest_path =
|
||||
if host_type == :WSL
|
||||
if guest_type == :linux
|
||||
dir_linux_path
|
||||
else
|
||||
dir_win_path
|
||||
end
|
||||
else
|
||||
# windows
|
||||
if guest_type == :linux
|
||||
dir_linux_path
|
||||
else
|
||||
dir_win_path
|
||||
end
|
||||
end
|
||||
mapping[:hyperv][win_path] = guest_path
|
||||
mapping[:platform][host_type == :Windows ? win_path : linux_path] = guest_path
|
||||
end
|
||||
|
||||
describe "#expand_excludes" do
|
||||
let(:hostpath) { 'vagrant' }
|
||||
let(:expanded_hostpaths) do
|
||||
|
@ -24,7 +107,6 @@ describe VagrantPlugins::HyperV::SyncHelper do
|
|||
end
|
||||
let(:exclude) { [".git/"] }
|
||||
let(:exclude_dirs) { %w[.vagrant/ .git/] }
|
||||
let(:separators) { { Windows: '\\', WSL: "/" } }
|
||||
|
||||
%i[Windows WSL].map do |host_type|
|
||||
context "in #{host_type} environment" do
|
||||
|
@ -74,6 +156,618 @@ describe VagrantPlugins::HyperV::SyncHelper do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#sync_single" do
|
||||
let(:hostpath) { 'vagrant' }
|
||||
let(:expanded_hostpaths) do
|
||||
{ Windows: 'C:\vagrant', WSL: "/vagrant" }
|
||||
end
|
||||
let(:guestpaths) do
|
||||
{ windows: 'C:\vagrant', linux: "/vagrant" }
|
||||
end
|
||||
let(:remote_guestdirs) do
|
||||
{ windows: 'C:\Windows\tmp', linux: "/tmp" }
|
||||
end
|
||||
let(:paths) do
|
||||
{ Windows: %w[C:\vagrant C:\vagrant\.vagrant C:\vagrant\.git C:\vagrant\test],
|
||||
WSL: %w[/vagrant /vagrant/.vagrant /vagrant/.git /vagrant/test] }
|
||||
end
|
||||
let(:exclude) { [".git/"] }
|
||||
let(:ssh_info) { { username: "vagrant" } }
|
||||
let(:no_compression) { false }
|
||||
|
||||
%i[windows linux].map do |guest_type|
|
||||
context "#{guest_type} guest" do
|
||||
let(:guest_type) { guest_type }
|
||||
let(:is_win_guest) { guest_type == :windows }
|
||||
let(:guestpath) { guestpaths[guest_type] }
|
||||
let(:remote_guestdir) { remote_guestdirs[guest_type] }
|
||||
|
||||
before { allow(guest).to receive(:name).and_return(guest_type) }
|
||||
|
||||
%i[Windows WSL].map do |host_type|
|
||||
let(:host_type) { host_type }
|
||||
let(:separator) { separators[host_type] }
|
||||
let(:input_paths) { paths[host_type] }
|
||||
let(:expanded_hostpath) { expanded_hostpaths[host_type] }
|
||||
let(:test_data) { generate_test_data input_paths, separator }
|
||||
let(:test_includes) { test_data[:includes] }
|
||||
let(:folder_opts) do
|
||||
h = { hostpath: hostpath,
|
||||
guestpath: guestpath,
|
||||
exclude: exclude }
|
||||
h = !no_compression ? h : h.dup.merge({no_compression: no_compression})
|
||||
h
|
||||
end
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:expand_path).
|
||||
with(hostpath).and_return(expanded_hostpath)
|
||||
end
|
||||
|
||||
after { subject.sync_single(machine, ssh_info, folder_opts) }
|
||||
|
||||
context "in #{host_type} environment" do
|
||||
before do
|
||||
allow(subject).to receive(:find_includes).with(hostpath, exclude).and_return(test_includes)
|
||||
end
|
||||
|
||||
context "with no compression" do
|
||||
let(:no_compression) { true }
|
||||
let(:dir_mappings) do
|
||||
mappings = { hyperv: {}, platform: {} }
|
||||
test_includes[:dirs].map do |dir|
|
||||
convert_path(mappings, dir, host_type, guest_type, is_file: false)
|
||||
end
|
||||
mappings
|
||||
end
|
||||
let(:files_mappings) do
|
||||
mappings = { hyperv: {}, platform: {} }
|
||||
test_includes[:files].map do |file|
|
||||
convert_path(mappings, file, host_type, guest_type, is_file: true)
|
||||
end
|
||||
mappings
|
||||
end
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:path_mapping).
|
||||
with(hostpath, guestpath, test_includes, is_win_guest: is_win_guest).
|
||||
and_return({dirs: dir_mappings, files: files_mappings})
|
||||
allow(subject).to receive(:remove_directory).
|
||||
with(machine, guestpath, is_win_guest: is_win_guest, sudo: true)
|
||||
allow(guest).to receive(:capability).
|
||||
with(:create_directories, dir_mappings[:hyperv].values, sudo: true)
|
||||
allow(subject).to receive(:hyperv_copy?).with(machine).and_return(true)
|
||||
allow(driver).to receive(:sync_files).
|
||||
with(machine.id, dir_mappings[:hyperv], files_mappings[:hyperv], is_win_guest: is_win_guest)
|
||||
end
|
||||
|
||||
context "copy with Hyper-V daemons" do
|
||||
it "calls driver#sync_files to sync all files at once" do
|
||||
expect(driver).to receive(:sync_files).
|
||||
with(machine.id, dir_mappings[:hyperv], files_mappings[:hyperv], is_win_guest: is_win_guest)
|
||||
end
|
||||
end
|
||||
|
||||
context "copy with WinRM" do
|
||||
let(:stat) { double("stat", symlink?: false)}
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:hyperv_copy?).with(machine).and_return(false)
|
||||
allow(subject).to receive(:file_exist?).and_return(true)
|
||||
allow(subject).to receive(:file_stat).and_return(stat)
|
||||
allow(comm).to receive(:upload)
|
||||
end
|
||||
|
||||
it "calls WinRM to upload files" do
|
||||
files_mappings[:platform].each do |host_path, guest_path|
|
||||
expect(subject).to receive(:file_exist?).ordered.with(host_path).and_return(true)
|
||||
expect(subject).to receive(:file_stat).ordered.with(host_path).and_return(stat)
|
||||
expect(comm).to receive(:upload).ordered.with(host_path, guest_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "removes destination dir and creates directory structure on guest" do
|
||||
expect(subject).to receive(:remove_directory).
|
||||
with(machine, guestpath, is_win_guest: is_win_guest, sudo: true)
|
||||
expect(guest).to receive(:capability).
|
||||
with(:create_directories, dir_mappings[:hyperv].values, sudo: true)
|
||||
end
|
||||
end
|
||||
|
||||
context "with compression" do
|
||||
let(:compression_type) { guest_type == :windows ? :zip : :tgz }
|
||||
let(:remote_guestpath) { [remote_guestdir, "remote_#{compression_type}"].join separator }
|
||||
let(:archive_name) { [expanded_hostpath, "vagrant_tmp.#{compression_type}"].join separator }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:compress_source_zip).
|
||||
with(expanded_hostpath, test_includes[:files]).and_return(archive_name)
|
||||
allow(subject).to receive(:compress_source_tgz).
|
||||
with(expanded_hostpath, test_includes[:files]).and_return(archive_name)
|
||||
allow(guest).to receive(:capability).
|
||||
with(:create_tmp_path, extension: ".#{compression_type}").and_return(remote_guestpath)
|
||||
allow(subject).to receive(:upload_file).
|
||||
with(machine, archive_name, remote_guestpath, is_win_guest: is_win_guest)
|
||||
allow(subject).to receive(:remove_directory).
|
||||
with(machine, guestpath, is_win_guest: is_win_guest, sudo: true)
|
||||
allow(guest).to receive(:capability).
|
||||
with("decompress_#{compression_type}".to_sym, remote_guestpath, guestpath, type: :directory, sudo: true)
|
||||
allow(subject).to receive(:file_exist?).with(archive_name).and_return(true)
|
||||
allow(FileUtils).to receive(:rm_f).with(archive_name)
|
||||
end
|
||||
|
||||
it "compresses the host directory to archive" do
|
||||
expect(subject).to receive("compress_source_#{compression_type}".to_sym).
|
||||
with(expanded_hostpath, test_includes[:files]).and_return(archive_name)
|
||||
end
|
||||
|
||||
it "creates temporary path on guest" do
|
||||
expect(guest).to receive(:capability).
|
||||
with(:create_tmp_path, extension: ".#{compression_type}").and_return(remote_guestpath)
|
||||
end
|
||||
|
||||
it "uploads archive file to temporary path on guest" do
|
||||
allow(subject).to receive(:upload_file).
|
||||
with(machine, archive_name, remote_guestpath, is_win_guest: is_win_guest)
|
||||
end
|
||||
|
||||
it "removes destination dir and decompresses archive file at temporary path on guest" do
|
||||
expect(subject).to receive(:remove_directory).
|
||||
with(machine, guestpath, is_win_guest: is_win_guest, sudo: true)
|
||||
expect(guest).to receive(:capability).
|
||||
with("decompress_#{compression_type}".to_sym, remote_guestpath, guestpath, type: :directory, sudo: true)
|
||||
end
|
||||
|
||||
it "removes temporary archive file" do
|
||||
expect(FileUtils).to receive(:rm_f).with(archive_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#find_includes" do
|
||||
let(:hostpath) { 'vagrant' }
|
||||
let(:expanded_hostpaths) do
|
||||
{ Windows: 'C:\vagrant', WSL: "/vagrant" }
|
||||
end
|
||||
let(:exclude) { [".git/"] }
|
||||
let(:paths) do
|
||||
{ Windows: %w[C:\vagrant C:\vagrant\.vagrant C:\vagrant\.git C:\vagrant\test],
|
||||
WSL: %w[/vagrant /vagrant/.vagrant /vagrant/.git /vagrant/test] }
|
||||
end
|
||||
|
||||
%i[windows linux].map do |guest_type|
|
||||
context "#{guest_type} guest" do
|
||||
%i[Windows WSL].map do |host_type|
|
||||
context "in #{host_type} environment" do
|
||||
let(:host_type) { host_type }
|
||||
let(:separator) { separators[host_type] }
|
||||
let(:input_paths) { paths[host_type] }
|
||||
let(:expanded_hostpath) { expanded_hostpaths[host_type] }
|
||||
let(:test_data) { generate_test_data input_paths, separator }
|
||||
let(:test_files) { test_data[:files] }
|
||||
let(:test_includes) { test_data[:includes] }
|
||||
let(:test_excludes) { test_data[:excludes] }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:expand_path).
|
||||
with(hostpath).and_return(expanded_hostpath)
|
||||
allow(subject).to receive(:expand_excludes).
|
||||
with(hostpath, exclude).and_return(test_excludes)
|
||||
allow(Find).to receive(:find).with(expanded_hostpath) do |arg, &proc|
|
||||
test_files.map do |file|
|
||||
proc.call file
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
expect(described_class.send(:find_includes, hostpath, exclude)).to eq(test_includes)
|
||||
end
|
||||
|
||||
it "expands host path to full path" do
|
||||
allow(subject).to receive(:expand_path).
|
||||
with(hostpath).and_return(expanded_hostpath)
|
||||
end
|
||||
|
||||
it "expands excluded files and directories for exclusion" do
|
||||
allow(subject).to receive(:expand_excludes).
|
||||
with(hostpath, exclude).and_return(test_excludes)
|
||||
end
|
||||
|
||||
it "locates all files in expanded host path" do
|
||||
expect(Find).to receive(:find).with(expanded_hostpath)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#path_mapping" do
|
||||
let(:hostpath) { 'vagrant' }
|
||||
let(:expanded_hostpaths) do
|
||||
{ Windows: 'C:\vagrant', WSL: "/vagrant" }
|
||||
end
|
||||
let(:guestpaths) do
|
||||
{ windows: 'C:\vagrant', linux: "/vagrant" }
|
||||
end
|
||||
let(:paths) do
|
||||
{ Windows: %w[C:\vagrant C:\vagrant\.vagrant C:\vagrant\.git C:\vagrant\test],
|
||||
WSL: %w[/vagrant /vagrant/.vagrant /vagrant/.git /vagrant/test] }
|
||||
end
|
||||
|
||||
%i[windows linux].map do |guest_type|
|
||||
context "maps dirs and files for copy on #{guest_type} guest" do
|
||||
let(:guest_type) { guest_type }
|
||||
let(:is_win_guest) { guest_type == :windows }
|
||||
|
||||
%i[Windows WSL].map do |host_type|
|
||||
context "in #{host_type} environment" do
|
||||
let(:is_windows) { host_type == :Windows }
|
||||
let(:host_type) { host_type }
|
||||
let(:separator) { separators[host_type] }
|
||||
let(:input_paths) { paths[host_type] }
|
||||
let(:expanded_hostpath) { expanded_hostpaths[host_type] }
|
||||
let(:expanded_hostpath_windows) { expanded_hostpaths[:Windows] }
|
||||
let(:guestpath) { guestpaths[guest_type] }
|
||||
let(:test_data) { generate_test_data input_paths, separator }
|
||||
let(:includes) { test_data[:includes] }
|
||||
let(:dir_mappings) do
|
||||
mappings = { hyperv: {}, platform: {} }
|
||||
includes[:dirs].map do |dir|
|
||||
convert_path(mappings, dir, host_type, guest_type, is_file: false)
|
||||
end
|
||||
mappings
|
||||
end
|
||||
let(:files_mappings) do
|
||||
mappings = { hyperv: {}, platform: {} }
|
||||
includes[:files].map do |file|
|
||||
convert_path(mappings, file, host_type, guest_type, is_file: true)
|
||||
end
|
||||
mappings
|
||||
end
|
||||
let(:opts) do
|
||||
shared_folder.dup.tap do |opts|
|
||||
opts[:guestpath] = guestpath
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:expand_path).
|
||||
with(hostpath).and_return(expanded_hostpath)
|
||||
allow(Vagrant::Util::Platform).to receive(:wsl?).and_return(!is_windows)
|
||||
allow(Vagrant::Util::Platform).to receive(:windows_path).
|
||||
with(expanded_hostpath, :disable_unc).and_return(expanded_hostpath_windows)
|
||||
end
|
||||
|
||||
after { expect(subject.path_mapping(hostpath, guestpath, includes, is_win_guest: is_win_guest)).to eq({ dirs: dir_mappings, files: files_mappings }) }
|
||||
|
||||
it "expands host path to full path" do
|
||||
expect(subject).to receive(:expand_path).
|
||||
with(hostpath).and_return(expanded_hostpath)
|
||||
end
|
||||
|
||||
it "formats expanded full path to windows path" do
|
||||
expect(Vagrant::Util::Platform).to receive(:windows_path).
|
||||
with(expanded_hostpath, :disable_unc).and_return(expanded_hostpath_windows)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#compress_source_zip" do
|
||||
let(:windows_temps) { { Windows: 'C:\Windows\tmp', WSL: "/mnt/c/Windows/tmp" } }
|
||||
let(:paths) do
|
||||
{ Windows: 'C:\vagrant', WSL: "/vagrant" }
|
||||
end
|
||||
let(:dir_items) { { Windows: 'C:\vagrant\dir1', WSL: '/vagrant/dir1' } }
|
||||
let(:source_items) { { Windows: %w(C:\vagrant\file1 C:\vagrant\file2 C:\vagrant\dir1 C:\vagrant\dir1\file2),
|
||||
WSL: %w(/vagrant/file1 /vagrant/file2 /vagrant/dir1 /vagrant/dir1/file2) } }
|
||||
|
||||
%i[Windows WSL].map do |host_type|
|
||||
context "in #{host_type} environment" do
|
||||
let(:is_windows) { host_type == :Windows }
|
||||
let(:host_type) { host_type }
|
||||
let(:separator) { separators[host_type] }
|
||||
let(:windows_temp) { windows_temps[host_type] }
|
||||
let(:path) { paths[host_type] }
|
||||
let(:dir_item) { dir_items[host_type] }
|
||||
let(:platform_source_items) { source_items[host_type] }
|
||||
let(:zip_path) { [windows_temp, "vagrant_test_tmp.zip"].join separator }
|
||||
let(:zip_file) { double("zip_file", path: zip_path) }
|
||||
let(:zip) { double("zip") }
|
||||
let(:stat) { double("stat", symlink?: false)}
|
||||
let(:zip_output_stream) { double("zip_output_stream") }
|
||||
let(:source_file) { double("source_file") }
|
||||
let(:content) { "ABC" }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:format_windows_temp).and_return(windows_temp)
|
||||
allow(Tempfile).to receive(:create).and_return(zip_file)
|
||||
allow(zip_file).to receive(:close)
|
||||
allow(Zip::File).to receive(:open).with(zip_path, Zip::File::CREATE).and_yield(zip)
|
||||
|
||||
allow(subject).to receive(:file_exist?).and_return(true)
|
||||
allow(subject).to receive(:file_stat).and_return(stat)
|
||||
allow(subject).to receive(:directory?).and_return(false)
|
||||
allow(subject).to receive(:directory?).with(dir_item).and_return(true)
|
||||
|
||||
allow(zip).to receive(:get_entry).with(/[\.|dir?]/).and_raise(Errno::ENOENT)
|
||||
allow(zip).to receive(:mkdir).with(/[\.|dir?]/)
|
||||
allow(zip).to receive(:get_output_stream).with(/.*file?/).and_yield(zip_output_stream)
|
||||
allow(File).to receive(:open).with(/.*/, "rb").and_return(source_file)
|
||||
allow(source_file).to receive(:read).with(2048).and_return(content, nil)
|
||||
allow(zip_output_stream).to receive(:write).with(content)
|
||||
end
|
||||
|
||||
after { expect(subject.compress_source_zip(path, platform_source_items)).to eq(zip_path) }
|
||||
|
||||
it "creates a temporary file for writing" do
|
||||
expect(subject).to receive(:format_windows_temp).and_return(windows_temp)
|
||||
expect(Tempfile).to receive(:create).and_return(zip_file)
|
||||
expect(Zip::File).to receive(:open).with(zip_path, Zip::File::CREATE).and_yield(zip)
|
||||
end
|
||||
|
||||
it "skips directory" do
|
||||
expect(File).to receive(:open).with(dir_item, "rb").never
|
||||
end
|
||||
|
||||
it "writes file content to zip archive" do
|
||||
expect(File).to receive(:open).with(/.*/, "rb").and_return(source_file)
|
||||
expect(source_file).to receive(:read).with(2048).and_return(content, nil)
|
||||
expect(zip_output_stream).to receive(:write).with(content)
|
||||
end
|
||||
|
||||
it "processes all files" do
|
||||
allow(zip).to receive(:get_output_stream).with(/.*file?/).exactly(platform_source_items.length - 1).times
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#compress_source_tgz" do
|
||||
let(:windows_temps) { { Windows: 'C:\Windows\tmp', WSL: "/mnt/c/Windows/tmp" } }
|
||||
let(:paths) do
|
||||
{ Windows: 'C:\vagrant', WSL: "/vagrant" }
|
||||
end
|
||||
let(:dir_items) { { Windows: 'C:\vagrant\dir1', WSL: '/vagrant/dir1' } }
|
||||
let(:symlink_items) { { Windows: 'C:\vagrant\file2', WSL: '/vagrant/file2' } }
|
||||
let(:source_items) { { Windows: %w(C:\vagrant\file1 C:\vagrant\file2 C:\vagrant\dir1 C:\vagrant\dir1\file2),
|
||||
WSL: %w(/vagrant/file1 /vagrant/file2 /vagrant/dir1 /vagrant/dir1/file2) } }
|
||||
|
||||
%i[Windows WSL].map do |host_type|
|
||||
context "in #{host_type} environment" do
|
||||
let(:is_windows) { host_type == :Windows }
|
||||
let(:host_type) { host_type }
|
||||
let(:separator) { separators[host_type] }
|
||||
let(:windows_temp) { windows_temps[host_type] }
|
||||
let(:path) { paths[host_type] }
|
||||
let(:dir_item) { dir_items[host_type] }
|
||||
let(:symlink_item) { symlink_items[host_type] }
|
||||
let(:platform_source_items) { source_items[host_type] }
|
||||
let(:tar_path) { [windows_temp, "vagrant_test_tmp.tar"].join separator }
|
||||
let(:tgz_path) { [windows_temp, "vagrant_test_tmp.tgz"].join separator }
|
||||
let(:tar_file) { double("tar_file", path: tar_path) }
|
||||
let(:tgz_file) { double("tgz_file", path: tgz_path) }
|
||||
let(:tar) { double("tar") }
|
||||
let(:tgz) { double("tgz") }
|
||||
let(:file_mode) { 0744 }
|
||||
let(:stat) { double("stat", symlink?: false, mode: file_mode)}
|
||||
let(:stat_symlink) { double("stat_symlink", symlink?: true, mode: file_mode)}
|
||||
let(:tar_io) { double("tar_io") }
|
||||
let(:source_file) { double("source_file") }
|
||||
let(:content) { "ABC" }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:format_windows_temp).and_return(windows_temp)
|
||||
allow(Tempfile).to receive(:create).and_return(tar_file, tgz_file)
|
||||
allow(File).to receive(:open).with(tar_path, "wb+").and_return(tar_file)
|
||||
allow(File).to receive(:open).with(tgz_path, "wb").and_return(tgz_file)
|
||||
allow(Gem::Package::TarWriter).to receive(:new).with(tar_file).and_return(tar)
|
||||
allow(Zlib::GzipWriter).to receive(:new).with(tgz_file).and_return(tgz)
|
||||
|
||||
allow(File).to receive(:delete).with(tar_path)
|
||||
allow(tar_file).to receive(:close)
|
||||
allow(tar_file).to receive(:read)
|
||||
allow(tar_file).to receive(:rewind)
|
||||
allow(tgz_file).to receive(:close)
|
||||
|
||||
allow(tar).to receive(:mkdir)
|
||||
allow(tar).to receive(:add_symlink)
|
||||
allow(tar).to receive(:add_file).and_yield(tar_io)
|
||||
allow(tar).to receive(:close)
|
||||
allow(tgz).to receive(:mkdir)
|
||||
allow(tgz).to receive(:write)
|
||||
allow(tgz).to receive(:close)
|
||||
|
||||
allow(subject).to receive(:file_exist?).and_return(true)
|
||||
allow(subject).to receive(:file_stat).and_return(stat)
|
||||
allow(subject).to receive(:directory?).and_return(false)
|
||||
allow(subject).to receive(:directory?).with(dir_item).and_return(true)
|
||||
allow(File).to receive(:open).with(/.*/, "rb").and_yield(source_file)
|
||||
allow(source_file).to receive(:read).and_return(content, nil)
|
||||
allow(tar_io).to receive(:write)
|
||||
end
|
||||
|
||||
after { expect(subject.compress_source_tgz(path, platform_source_items)).to eq(tgz_path) }
|
||||
|
||||
it "creates temporary tar/tgz for writing" do
|
||||
expect(subject).to receive(:format_windows_temp).and_return(windows_temp)
|
||||
expect(Tempfile).to receive(:create).and_return(tar_file, tgz_file)
|
||||
expect(File).to receive(:open).with(tar_path, "wb+").and_return(tar_file)
|
||||
expect(File).to receive(:open).with(tgz_path, "wb").and_return(tgz_file)
|
||||
expect(Gem::Package::TarWriter).to receive(:new).with(tar_file).and_return(tar)
|
||||
expect(Zlib::GzipWriter).to receive(:new).with(tgz_file).and_return(tgz)
|
||||
end
|
||||
|
||||
it "creates directories in tar" do
|
||||
expect(tar).to receive(:mkdir).with(dir_item.sub(path, ""), file_mode)
|
||||
end
|
||||
|
||||
it "writes file content to tar archive" do
|
||||
expect(File).to receive(:open).with(/.*/, "rb").and_yield(source_file)
|
||||
expect(source_file).to receive(:read).and_return(content, nil)
|
||||
expect(tar_io).to receive(:write).with(content)
|
||||
end
|
||||
|
||||
it "deletes tar file eventually" do
|
||||
expect(File).to receive(:delete).with(tar_path)
|
||||
end
|
||||
|
||||
it "processes all files" do
|
||||
expect(tar).to receive(:add_file).with(/.*file?/, file_mode).exactly(platform_source_items.length - 1).times
|
||||
end
|
||||
|
||||
it "does not treat symlink as normal file" do
|
||||
allow(subject).to receive(:file_stat).with(symlink_item).and_return(stat_symlink)
|
||||
expect(File).to receive(:readlink).with(symlink_item).and_return("/target")
|
||||
expect(tar).to receive(:add_symlink).with(/.*file?/, "/target", file_mode)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#remove_directory" do
|
||||
let(:windows_path) { 'C:\Windows\Temp' }
|
||||
let(:unix_path) { "C:/Windows/Temp" }
|
||||
|
||||
[true, false].each do |sudo_flag|
|
||||
context "sudo flag: #{sudo_flag}" do
|
||||
it "calls powershell script to remove directory" do
|
||||
allow(subject).to receive(:to_windows_path).with(unix_path).and_return(windows_path)
|
||||
expect(comm).to receive(:execute).with(/.*if \(Test-Path\(\"C:\\Windows\\Temp\"\).*\n.*Remove-Item -Path \"C:\\Windows\\Temp\".*/, shell: :powershell)
|
||||
subject.remove_directory machine, unix_path, is_win_guest: true, sudo: sudo_flag
|
||||
end
|
||||
|
||||
it "calls linux command to remove directory forcibly" do
|
||||
allow(subject).to receive(:to_unix_path).with(windows_path).and_return(unix_path)
|
||||
expect(comm).to receive(:test).with("test -d '#{unix_path}'").and_return(true)
|
||||
expect(comm).to receive(:execute).with("rm -rf '#{unix_path}'", sudo: sudo_flag)
|
||||
subject.remove_directory machine, windows_path, is_win_guest: false, sudo: sudo_flag
|
||||
end
|
||||
|
||||
it "does not call rm when directory does not exist" do
|
||||
allow(subject).to receive(:to_unix_path).with(windows_path).and_return(unix_path)
|
||||
expect(comm).to receive(:test).with("test -d '#{unix_path}'").and_return(false)
|
||||
expect(comm).to receive(:execute).never
|
||||
subject.remove_directory machine, windows_path, is_win_guest: false, sudo: sudo_flag
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#format_windows_temp" do
|
||||
let(:windows_temp) { 'C:\Windows\tmp' }
|
||||
let(:unix_temp) { "/mnt/c/Windows/tmp" }
|
||||
|
||||
before { allow(Vagrant::Util::Platform).to receive(:windows_temp).and_return(windows_temp) }
|
||||
|
||||
it "returns Windows style temporary directory" do
|
||||
allow(Vagrant::Util::Platform).to receive(:wsl?).and_return(false)
|
||||
expect(subject.format_windows_temp).to eq(windows_temp)
|
||||
end
|
||||
|
||||
it "returns Unix style temporary directory in WSL" do
|
||||
allow(Vagrant::Util::Platform).to receive(:wsl?).and_return(true)
|
||||
expect(Vagrant::Util::Subprocess).to receive(:execute).
|
||||
with("wslpath", "-u", "-a", windows_temp).and_return(double(stdout: unix_temp, exit_code: 0))
|
||||
expect(subject.format_windows_temp).to eq(unix_temp)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#upload_file" do
|
||||
let(:sources) { { Windows: 'C:\vagrant\file1.zip', WSL: "/vagrant/file1.zip" } }
|
||||
let(:new_sources) { { Windows: 'C:\Windows\tmp\file2.zip', WSL: "/mnt/c/Windows/tmp/file2.zip" } }
|
||||
let(:windows_temps) { { Windows: 'C:\Windows\tmp', WSL: "/mnt/c/Windows/tmp" } }
|
||||
let(:dests) { { windows: 'C:\vagrant\file2.zip', linux: "/vagrant/file2.zip" } }
|
||||
let(:dest_dirs) { { windows: 'C:\vagrant', linux: "/vagrant" } }
|
||||
|
||||
%i[windows linux].map do |guest_type|
|
||||
context "#{guest_type} guest" do
|
||||
let(:guest_type) { guest_type }
|
||||
let(:dest) { dests[guest_type] }
|
||||
let(:dest_dir) { dest_dirs[guest_type] }
|
||||
|
||||
%i[Windows WSL].map do |host_type|
|
||||
context "in #{host_type} environment" do
|
||||
let(:host_type) { host_type }
|
||||
let(:is_windows) { host_type == :Windows }
|
||||
let(:source) { sources[host_type] }
|
||||
let(:new_source) { new_sources[host_type] }
|
||||
|
||||
context "uploads file by Hyper-V daemons when applicable" do
|
||||
let(:windows_temp) { windows_temps[host_type] }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:hyperv_copy?).with(machine).and_return(true)
|
||||
allow(subject).to receive(:format_windows_temp).and_return(windows_temp)
|
||||
allow(Vagrant::Util::Platform).to receive(:wsl?).and_return(!is_windows)
|
||||
allow(FileUtils).to receive(:rm_f)
|
||||
allow(FileUtils).to receive(:mv)
|
||||
allow(subject).to receive(:hyperv_copy)
|
||||
end
|
||||
|
||||
after { subject.upload_file machine, source, dest, is_win_guest: guest_type == :windows }
|
||||
|
||||
if host_type != :Windows
|
||||
it "moves the source file to new path with the destination filename" do
|
||||
expect(FileUtils).to receive(:mv).with(source, new_source)
|
||||
expect(FileUtils).to receive(:rm_f).with(new_source)
|
||||
end
|
||||
end
|
||||
|
||||
it "calls Hyper-V cmdlet to copy file" do
|
||||
expect(subject).to receive(:hyperv_copy).with(machine, new_source, dest_dir)
|
||||
end
|
||||
end
|
||||
|
||||
it "uploads file by WinRM when Hyper-V daemons are not applicable" do
|
||||
allow(subject).to receive(:hyperv_copy?).with(machine).and_return(false)
|
||||
expect(comm).to receive(:upload).with(source, dest)
|
||||
expect(subject).to receive(:hyperv_copy).never
|
||||
subject.upload_file machine, source, dest, is_win_guest: guest_type == :windows
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#hyperv_copy?" do
|
||||
before do
|
||||
allow(guest).to receive(:capability?)
|
||||
allow(guest).to receive(:capability)
|
||||
end
|
||||
|
||||
it "does not leverage Hyper-V daemons when guest does not support Hyper-V daemons" do
|
||||
allow(guest).to receive(:capability?).with(:hyperv_daemons_running).and_return(false)
|
||||
expect(guest).to receive(:capability).never
|
||||
end
|
||||
|
||||
it "checks whether Hyper-V daemons are running" do
|
||||
allow(guest).to receive(:capability?).with(:hyperv_daemons_running).and_return(true)
|
||||
allow(guest).to receive(:capability).with(:hyperv_daemons_running).and_return(true)
|
||||
expect(subject.hyperv_copy?(machine)).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#hyperv_copy" do
|
||||
let(:source) { 'C:\Windows\test' }
|
||||
let(:dest_dir) { "/vagrant" }
|
||||
|
||||
it "calls Copy-VMFile cmdlet to copy file to guest" do
|
||||
expect(Vagrant::Util::PowerShell).to receive(:execute_cmd).with(/.*Hyper-V\\Get-VM -Id \"vm_id\"\n.*Hyper-V\\Copy-VMFile -VM \$machine -SourcePath \"C:\\Windows\\test\" -DestinationPath \"#{dest_dir}\".*/)
|
||||
subject.hyperv_copy(machine, source, dest_dir)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#platform_join" do
|
||||
it "produces Windows-style path" do
|
||||
expect(subject.platform_join("C:", "vagrant", ".vagrant", "", is_windows: true)).to eq("C:\\vagrant\\.vagrant\\")
|
||||
|
@ -84,23 +778,88 @@ describe VagrantPlugins::HyperV::SyncHelper do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#sync_single" do
|
||||
let(:machine) { double("machine", provider: provider) }
|
||||
let(:provider) { double("provider") }
|
||||
let(:ssh_info) { { username: "vagrant" } }
|
||||
let(:folder_opts) do
|
||||
{ hostpath: 'vagrant',
|
||||
guestpath: 'C:\vagrant',
|
||||
owner: "vagrant",
|
||||
group: "vagrant",
|
||||
exclude: [".git/"] }
|
||||
describe "#platform_path" do
|
||||
let(:windows_path) { 'C:\Windows\Temp' }
|
||||
let(:unix_path) { "C:/Windows/Temp" }
|
||||
|
||||
it "returns Windows style path in Windows" do
|
||||
expect(subject.platform_path(unix_path, is_windows: true)).to eq(windows_path)
|
||||
end
|
||||
|
||||
after { subject.sync_single(machine, ssh_info, folder_opts) }
|
||||
it "returns Unix style path in WSL" do
|
||||
expect(subject.platform_path(windows_path, is_windows: false)).to eq(unix_path)
|
||||
end
|
||||
end
|
||||
|
||||
it "calls provider capability to sync single folder" do
|
||||
expect(provider).to receive(:capability).
|
||||
with(:sync_folder, folder_opts)
|
||||
describe "#to_windows_path" do
|
||||
let(:windows_path) { 'C:\Windows\Temp' }
|
||||
let(:unix_path) { "C:/Windows/Temp" }
|
||||
|
||||
it "converts path with unix separator to Windows" do
|
||||
expect(subject.to_windows_path(unix_path)).to eq(windows_path)
|
||||
end
|
||||
|
||||
it "keeps the original input for Windows path" do
|
||||
expect(subject.to_windows_path(windows_path)).to eq(windows_path)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#to_unix_path" do
|
||||
let(:windows_path) { '\usr\bin\test' }
|
||||
let(:unix_path) { "/usr/bin/test" }
|
||||
|
||||
it "converts path with Windows separator to Unix" do
|
||||
expect(subject.to_unix_path(windows_path)).to eq(unix_path)
|
||||
end
|
||||
|
||||
it "keeps the original input for Unix path" do
|
||||
expect(subject.to_unix_path(unix_path)).to eq(unix_path)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#trim_head" do
|
||||
let(:windows_path_no_heading) { 'usr\bin\test' }
|
||||
let(:unix_path_no_heading) { "usr/bin/test" }
|
||||
let(:windows_path_with_heading) { '\usr\bin\test' }
|
||||
let(:unix_path_with_heading) { "/usr/bin/test" }
|
||||
|
||||
it "keeps Windows path with no heading" do
|
||||
expect(subject.trim_head(windows_path_no_heading)).to eq(windows_path_no_heading)
|
||||
end
|
||||
|
||||
it "keeps Unix path with no heading" do
|
||||
expect(subject.trim_head(unix_path_no_heading)).to eq(unix_path_no_heading)
|
||||
end
|
||||
|
||||
it "removes heading separator from Windows path" do
|
||||
expect(subject.trim_head(windows_path_with_heading)).to eq(windows_path_no_heading)
|
||||
end
|
||||
|
||||
it "removes heading separator from Unix path" do
|
||||
expect(subject.trim_head(unix_path_with_heading)).to eq(unix_path_no_heading)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#trim_tail" do
|
||||
let(:windows_path_no_tailing) { '\usr\bin\test' }
|
||||
let(:unix_path_no_tailing) { "/usr/bin/test" }
|
||||
let(:windows_path_with_tailing) { '\usr\bin\test\\' }
|
||||
let(:unix_path_with_tailing) { "/usr/bin/test/" }
|
||||
|
||||
it "keeps Windows path with no tailing" do
|
||||
expect(subject.trim_tail(windows_path_no_tailing)).to eq(windows_path_no_tailing)
|
||||
end
|
||||
|
||||
it "keeps Unix path with no tailing" do
|
||||
expect(subject.trim_tail(unix_path_no_tailing)).to eq(unix_path_no_tailing)
|
||||
end
|
||||
|
||||
it "removes tailing separator from Windows path" do
|
||||
expect(subject.trim_tail(windows_path_with_tailing)).to eq(windows_path_no_tailing)
|
||||
end
|
||||
|
||||
it "removes tailing separator from Unix path" do
|
||||
expect(subject.trim_tail(unix_path_with_tailing)).to eq(unix_path_no_tailing)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue