From b897fd73651e263fc2b0fd364b7d6aba2f8f905d Mon Sep 17 00:00:00 2001 From: Lonnie VanZandt Date: Tue, 18 Aug 2015 10:56:13 -0600 Subject: [PATCH] Scrub Guest Paths for Windows Rsync leaving Dirty Paths for Winrm Mkdir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows offers no out-of-the-box rsync utility. By far, the most commonly used external utilities for Windows rsync are built with the GNU Cygwin libraries. The cost for this convenience is that rsync on Windows has to be provided paths that begin “/cygdrive/c” rather than “c:/“ like other Windows-API utilities. Compounding the situation, rsync doesn’t create paths/to/sub/targets and so the vagrant plugin code, when performing an rsync, is responsible for creating intermediate directories in guest paths if there are any. Furthermore, the mkdir utility in Windows is not another Cygwin utility like rsync but the routine mkdir of Windows command.com. Therefore, while rsync needs the /cygwin paths, mkdir uses the Windows paths. Later, the chef_solo.rp provisioner running within the guest will expect to find Windows-style paths in its solo.rb configuration file. Due to all this, vagrant has to keep track of both the original, possibly dirty Windows guest path and the cygwin-scrubbed guest path. --- plugins/guests/windows/cap/rsync.rb | 9 +++++++++ plugins/guests/windows/plugin.rb | 5 +++++ plugins/synced_folders/rsync/helper.rb | 5 +++++ 3 files changed, 19 insertions(+) diff --git a/plugins/guests/windows/cap/rsync.rb b/plugins/guests/windows/cap/rsync.rb index e391b92db..aa9f1bcdf 100644 --- a/plugins/guests/windows/cap/rsync.rb +++ b/plugins/guests/windows/cap/rsync.rb @@ -2,8 +2,17 @@ module VagrantPlugins module GuestWindows module Cap class RSync + def self.rsync_scrub_guestpath( machine, opts ) + # Windows guests most often use cygwin-dependent rsync utilities + # that expect "/cygdrive/c" instead of "c:" as the path prefix + # some vagrant code may pass guest paths with drive-lettered paths here + opts[:guestpath].gsub( /^([a-zA-Z]):/, '/cygdrive/\1' ) + end + def self.rsync_pre(machine, opts) machine.communicate.tap do |comm| + # rsync does not construct any gaps in the path to the target directory + # make sure that all subdirectories are created comm.execute("mkdir '#{opts[:guestpath]}'") end end diff --git a/plugins/guests/windows/plugin.rb b/plugins/guests/windows/plugin.rb index 47ca67e3f..d22dc2743 100644 --- a/plugins/guests/windows/plugin.rb +++ b/plugins/guests/windows/plugin.rb @@ -64,6 +64,11 @@ module VagrantPlugins Cap::MountSharedFolder end + guest_capability(:windows, :rsync_scrub_guestpath) do + require_relative "cap/rsync" + Cap::RSync + end + guest_capability(:windows, :rsync_pre) do require_relative "cap/rsync" Cap::RSync diff --git a/plugins/synced_folders/rsync/helper.rb b/plugins/synced_folders/rsync/helper.rb index 594410436..e155d61f7 100644 --- a/plugins/synced_folders/rsync/helper.rb +++ b/plugins/synced_folders/rsync/helper.rb @@ -38,6 +38,11 @@ module VagrantPlugins hostpath = File.expand_path(hostpath, machine.env.root_path) hostpath = Vagrant::Util::Platform.fs_real_path(hostpath).to_s + # if the guest has a guest path scrubber capability, use it + if machine.guest.capability?(:rsync_scrub_guestpath) + guestpath = machine.guest.capability(:rsync_scrub_guestpath, opts) + end + if Vagrant::Util::Platform.windows? # rsync for Windows expects cygwin style paths, always. hostpath = Vagrant::Util::Platform.cygwin_path(hostpath)