diff --git a/plugins/guests/linux/cap/rsync.rb b/plugins/guests/linux/cap/rsync.rb new file mode 100644 index 000000000..2bed51e33 --- /dev/null +++ b/plugins/guests/linux/cap/rsync.rb @@ -0,0 +1,16 @@ +module VagrantPlugins + module GuestLinux + module Cap + class RSync + def self.rsync_pre(machine, folder_opts) + username = machine.ssh_info[:username] + + machine.communicate.tap do |comm| + comm.sudo("mkdir -p '#{folder_opts[:guestpath]}'") + comm.sudo("chown -R #{username} '#{folder_opts[:guestpath]}'") + end + end + end + end + end +end diff --git a/plugins/guests/linux/plugin.rb b/plugins/guests/linux/plugin.rb index 42abed371..fb91b722c 100644 --- a/plugins/guests/linux/plugin.rb +++ b/plugins/guests/linux/plugin.rb @@ -45,6 +45,12 @@ module VagrantPlugins require_relative "cap/read_ip_address" Cap::ReadIPAddress end + + # RSync synced folders + guest_capability("linux", "rsync_pre") do + require_relative "cap/rsync" + Cap::RSync + end end end end diff --git a/plugins/synced_folders/rsync/synced_folder.rb b/plugins/synced_folders/rsync/synced_folder.rb index a96a8678c..b8eba169a 100644 --- a/plugins/synced_folders/rsync/synced_folder.rb +++ b/plugins/synced_folders/rsync/synced_folder.rb @@ -26,16 +26,15 @@ module VagrantPlugins end def enable(machine, folders, opts) - rootdir = machine.env.root_path.to_s ssh_info = machine.ssh_info folders.each do |id, folder_opts| - rsync_single(ssh_info, rootdir, machine.ui, folder_opts) + rsync_single(machine, ssh_info, folder_opts) end end # rsync_single rsync's a single folder with the given options. - def rsync_single(ssh_info, rootdir, ui, opts) + def rsync_single(machine, ssh_info, opts) # Folder info guestpath = opts[:guestpath] hostpath = opts[:hostpath] @@ -64,14 +63,19 @@ module VagrantPlugins hostpath, "#{username}@#{host}:#{guestpath}" ].flatten - command_opts = {} # The working directory should be the root path - command_opts[:workdir] = rootdir + command_opts[:workdir] = machine.env.root_path.to_s - ui.info(I18n.t( + machine.ui.info(I18n.t( "vagrant.rsync_folder", guestpath: guestpath, hostpath: hostpath)) + + # If we have tasks to do before rsyncing, do those. + if machine.guest.capability?(:rsync_pre) + machine.guest.capability(:rsync_pre, opts) + end + r = Vagrant::Util::Subprocess.execute(*(command + [command_opts])) if r.exit_code != 0 raise Vagrant::Errors::RSyncError, diff --git a/test/unit/plugins/synced_folders/rsync/synced_folder_test.rb b/test/unit/plugins/synced_folders/rsync/synced_folder_test.rb index 97a689a63..61990b3ae 100644 --- a/test/unit/plugins/synced_folders/rsync/synced_folder_test.rb +++ b/test/unit/plugins/synced_folders/rsync/synced_folder_test.rb @@ -12,11 +12,13 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do env.create_vagrant_env end + let(:guest) { double("guest") } let(:host) { double("host") } let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) } before do machine.env.stub(host: host) + machine.stub(guest: guest) end describe "#usable?" do @@ -52,7 +54,7 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do folders.each do |_, opts| subject.should_receive(:rsync_single). - with(ssh_info, machine.env.root_path.to_s, machine.ui, opts). + with(machine, ssh_info, opts). ordered end @@ -67,22 +69,23 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do private_key_path: [], }} let(:opts) { {} } - let(:root_path) { "foo" } let(:ui) { machine.ui } before do Vagrant::Util::Subprocess.stub(execute: result) + + guest.stub(capability?: false) end it "doesn't raise an error if it succeeds" do - subject.rsync_single(ssh_info, root_path, ui, opts) + subject.rsync_single(machine, ssh_info, opts) end it "raises an error if the exit code is non-zero" do Vagrant::Util::Subprocess.stub( execute: Vagrant::Util::Subprocess::Result.new(1, "", "")) - expect {subject.rsync_single(ssh_info, root_path, ui, opts) }. + expect {subject.rsync_single(machine, ssh_info, opts) }. to raise_error(Vagrant::Errors::RSyncError) end @@ -91,10 +94,18 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do expect(args.last).to be_kind_of(Hash) opts = args.last - expect(opts[:workdir]).to eql(root_path) + expect(opts[:workdir]).to eql(machine.env.root_path.to_s) end - subject.rsync_single(ssh_info, root_path, ui, opts) + subject.rsync_single(machine, ssh_info, opts) + end + + it "executes the rsync_pre capability first if it exists" do + guest.should_receive(:capability?).with(:rsync_pre).and_return(true) + guest.should_receive(:capability).with(:rsync_pre, opts).ordered + Vagrant::Util::Subprocess.should_receive(:execute).ordered.and_return(result) + + subject.rsync_single(machine, ssh_info, opts) end end end