Merge pull request #2816 from mitchellh/f-rsync-command
"vagrant rsync" non-primary command
This commit is contained in:
commit
54bb182525
|
@ -1,7 +1,11 @@
|
||||||
|
require 'vagrant/util/scoped_hash_override'
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module Action
|
module Action
|
||||||
module Builtin
|
module Builtin
|
||||||
module MixinSyncedFolders
|
module MixinSyncedFolders
|
||||||
|
include Vagrant::Util::ScopedHashOverride
|
||||||
|
|
||||||
# This goes over all the registered synced folder types and returns
|
# This goes over all the registered synced folder types and returns
|
||||||
# the highest priority implementation that is usable for this machine.
|
# the highest priority implementation that is usable for this machine.
|
||||||
def default_synced_folder_type(machine, plugins)
|
def default_synced_folder_type(machine, plugins)
|
||||||
|
@ -96,6 +100,13 @@ module Vagrant
|
||||||
folders.delete("")
|
folders.delete("")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Apply the scoped hash overrides to get the options
|
||||||
|
folders.each do |impl_name, fs|
|
||||||
|
fs.each do |id, data|
|
||||||
|
fs[id] = scoped_hash_override(data, impl_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return folders
|
return folders
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
|
||||||
require 'vagrant/util/platform'
|
require 'vagrant/util/platform'
|
||||||
require 'vagrant/util/scoped_hash_override'
|
|
||||||
|
|
||||||
require_relative "mixin_synced_folders"
|
require_relative "mixin_synced_folders"
|
||||||
|
|
||||||
|
@ -12,7 +11,6 @@ module Vagrant
|
||||||
# the appropriate synced folder plugin.
|
# the appropriate synced folder plugin.
|
||||||
class SyncedFolders
|
class SyncedFolders
|
||||||
include MixinSyncedFolders
|
include MixinSyncedFolders
|
||||||
include Vagrant::Util::ScopedHashOverride
|
|
||||||
|
|
||||||
def initialize(app, env)
|
def initialize(app, env)
|
||||||
@app = app
|
@app = app
|
||||||
|
@ -28,9 +26,6 @@ module Vagrant
|
||||||
fs.each do |id, data|
|
fs.each do |id, data|
|
||||||
# Log every implementation and their paths
|
# Log every implementation and their paths
|
||||||
@logger.info(" - #{id}: #{data[:hostpath]} => #{data[:guestpath]}")
|
@logger.info(" - #{id}: #{data[:hostpath]} => #{data[:guestpath]}")
|
||||||
|
|
||||||
# Scope hash override
|
|
||||||
fs[id] = scoped_hash_override(data, impl_name)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -324,7 +324,7 @@ module Vagrant
|
||||||
# Returns the state of this machine. The state is queried from the
|
# Returns the state of this machine. The state is queried from the
|
||||||
# backing provider, so it can be any arbitrary symbol.
|
# backing provider, so it can be any arbitrary symbol.
|
||||||
#
|
#
|
||||||
# @return [Symbol]
|
# @return [MachineState]
|
||||||
def state
|
def state
|
||||||
result = @provider.state
|
result = @provider.state
|
||||||
raise Errors::MachineStateInvalid if !result.is_a?(MachineState)
|
raise Errors::MachineStateInvalid if !result.is_a?(MachineState)
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
require "vagrant/action/builtin/mixin_synced_folders"
|
||||||
|
|
||||||
|
require_relative "../helper"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module SyncedFolderRSync
|
||||||
|
module Command
|
||||||
|
class Rsync < Vagrant.plugin("2", :command)
|
||||||
|
include Vagrant::Action::Builtin::MixinSyncedFolders
|
||||||
|
|
||||||
|
def self.synopsis
|
||||||
|
"syncs rsync synced folders to remote machine"
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute
|
||||||
|
opts = OptionParser.new do |o|
|
||||||
|
o.banner = "Usage: vagrant rsync [vm-name]"
|
||||||
|
o.separator ""
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse the options and return if we don't have any target.
|
||||||
|
argv = parse_options(opts)
|
||||||
|
return if !argv
|
||||||
|
|
||||||
|
# Go through each machine and perform the rsync
|
||||||
|
error = false
|
||||||
|
with_target_vms(argv) do |machine|
|
||||||
|
if !machine.communicate.ready?
|
||||||
|
machine.ui.error(I18n.t("vagrant.rsync_communicator_not_ready"))
|
||||||
|
error = true
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
# Determine the rsync synced folders for this machine
|
||||||
|
folders = synced_folders(machine)[:rsync]
|
||||||
|
next if !folders || folders.empty?
|
||||||
|
|
||||||
|
# Get the SSH info for this machine so we can access it
|
||||||
|
ssh_info = machine.ssh_info
|
||||||
|
|
||||||
|
# Sync them!
|
||||||
|
folders.each do |id, folder_opts|
|
||||||
|
RsyncHelper.rsync_single(machine, ssh_info, folder_opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return error ? 1 : 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,68 @@
|
||||||
|
require "vagrant/util/subprocess"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module SyncedFolderRSync
|
||||||
|
# This is a helper that abstracts out the functionality of rsyncing
|
||||||
|
# folders so that it can be called from anywhere.
|
||||||
|
class RsyncHelper
|
||||||
|
def self.rsync_single(machine, ssh_info, opts)
|
||||||
|
# Folder info
|
||||||
|
guestpath = opts[:guestpath]
|
||||||
|
hostpath = opts[:hostpath]
|
||||||
|
hostpath = File.expand_path(hostpath, machine.env.root_path)
|
||||||
|
|
||||||
|
# Connection information
|
||||||
|
username = ssh_info[:username]
|
||||||
|
host = ssh_info[:host]
|
||||||
|
rsh = [
|
||||||
|
"ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no",
|
||||||
|
ssh_info[:private_key_path].map { |p| "-i '#{p}'" },
|
||||||
|
].flatten.join(" ")
|
||||||
|
|
||||||
|
# Exclude some files by default, and any that might be configured
|
||||||
|
# by the user.
|
||||||
|
excludes = ['.vagrant/']
|
||||||
|
excludes += Array(opts[:exclude]).map(&:to_s) if opts[:exclude]
|
||||||
|
excludes.uniq!
|
||||||
|
|
||||||
|
# Build up the actual command to execute
|
||||||
|
command = [
|
||||||
|
"rsync",
|
||||||
|
"--verbose",
|
||||||
|
"--archive",
|
||||||
|
"--delete",
|
||||||
|
"-z",
|
||||||
|
excludes.map { |e| ["--exclude", e] },
|
||||||
|
"-e", rsh,
|
||||||
|
hostpath,
|
||||||
|
"#{username}@#{host}:#{guestpath}"
|
||||||
|
].flatten
|
||||||
|
command_opts = {}
|
||||||
|
|
||||||
|
# The working directory should be the root path
|
||||||
|
command_opts[:workdir] = machine.env.root_path.to_s
|
||||||
|
|
||||||
|
machine.ui.info(I18n.t(
|
||||||
|
"vagrant.rsync_folder", guestpath: guestpath, hostpath: hostpath))
|
||||||
|
if excludes.length > 1
|
||||||
|
machine.ui.info(I18n.t(
|
||||||
|
"vagrant.rsync_folder_excludes", excludes: excludes.inspect))
|
||||||
|
end
|
||||||
|
|
||||||
|
# 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,
|
||||||
|
command: command.join(" "),
|
||||||
|
guestpath: guestpath,
|
||||||
|
hostpath: hostpath,
|
||||||
|
stderr: r.stderr
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,6 +9,11 @@ module VagrantPlugins
|
||||||
The Rsync synced folder plugin will sync folders via rsync.
|
The Rsync synced folder plugin will sync folders via rsync.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
command("rsync", primary: false) do
|
||||||
|
require_relative "command/rsync"
|
||||||
|
Command::Rsync
|
||||||
|
end
|
||||||
|
|
||||||
synced_folder("rsync", 5) do
|
synced_folder("rsync", 5) do
|
||||||
require_relative "synced_folder"
|
require_relative "synced_folder"
|
||||||
SyncedFolder
|
SyncedFolder
|
||||||
|
|
|
@ -3,6 +3,8 @@ require "log4r"
|
||||||
require "vagrant/util/subprocess"
|
require "vagrant/util/subprocess"
|
||||||
require "vagrant/util/which"
|
require "vagrant/util/which"
|
||||||
|
|
||||||
|
require_relative "helper"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module SyncedFolderRSync
|
module SyncedFolderRSync
|
||||||
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
||||||
|
@ -33,65 +35,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
folders.each do |id, folder_opts|
|
folders.each do |id, folder_opts|
|
||||||
rsync_single(machine, ssh_info, folder_opts)
|
RsyncHelper.rsync_single(machine, ssh_info, folder_opts)
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# rsync_single rsync's a single folder with the given options.
|
|
||||||
def rsync_single(machine, ssh_info, opts)
|
|
||||||
# Folder info
|
|
||||||
guestpath = opts[:guestpath]
|
|
||||||
hostpath = opts[:hostpath]
|
|
||||||
|
|
||||||
# Connection information
|
|
||||||
username = ssh_info[:username]
|
|
||||||
host = ssh_info[:host]
|
|
||||||
rsh = [
|
|
||||||
"ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no",
|
|
||||||
ssh_info[:private_key_path].map { |p| "-i '#{p}'" },
|
|
||||||
].flatten.join(" ")
|
|
||||||
|
|
||||||
# Exclude some files by default, and any that might be configured
|
|
||||||
# by the user.
|
|
||||||
excludes = ['.vagrant/']
|
|
||||||
excludes += Array(opts[:exclude]).map(&:to_s) if opts[:exclude]
|
|
||||||
excludes.uniq!
|
|
||||||
|
|
||||||
# Build up the actual command to execute
|
|
||||||
command = [
|
|
||||||
"rsync",
|
|
||||||
"--verbose",
|
|
||||||
"--archive",
|
|
||||||
"-z",
|
|
||||||
excludes.map { |e| ["--exclude", e] },
|
|
||||||
"-e", rsh,
|
|
||||||
hostpath,
|
|
||||||
"#{username}@#{host}:#{guestpath}"
|
|
||||||
].flatten
|
|
||||||
command_opts = {}
|
|
||||||
|
|
||||||
# The working directory should be the root path
|
|
||||||
command_opts[:workdir] = machine.env.root_path.to_s
|
|
||||||
|
|
||||||
machine.ui.info(I18n.t(
|
|
||||||
"vagrant.rsync_folder", guestpath: guestpath, hostpath: hostpath))
|
|
||||||
if excludes.length > 1
|
|
||||||
machine.ui.info(I18n.t(
|
|
||||||
"vagrant.rsync_folder_excludes", excludes: excludes.inspect))
|
|
||||||
end
|
|
||||||
|
|
||||||
# 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,
|
|
||||||
command: command.join(" "),
|
|
||||||
guestpath: guestpath,
|
|
||||||
hostpath: hostpath,
|
|
||||||
stderr: r.stderr
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -85,6 +85,9 @@ en:
|
||||||
%{names}
|
%{names}
|
||||||
provisioner_cleanup: |-
|
provisioner_cleanup: |-
|
||||||
Running cleanup tasks for '%{name}' provisioner...
|
Running cleanup tasks for '%{name}' provisioner...
|
||||||
|
rsync_communicator_not_ready: |-
|
||||||
|
The machine is reporting that it is not ready for rsync to
|
||||||
|
communiate with it. Verify that this machine is properly running.
|
||||||
rsync_folder: |-
|
rsync_folder: |-
|
||||||
Rsyncing folder: %{hostpath} => %{guestpath}
|
Rsyncing folder: %{hostpath} => %{guestpath}
|
||||||
rsync_folder_excludes: " - Exclude: %{excludes}"
|
rsync_folder_excludes: " - Exclude: %{excludes}"
|
||||||
|
|
|
@ -31,6 +31,9 @@ end
|
||||||
# Vagrantfile anywhere, or at least this minimizes those chances.
|
# Vagrantfile anywhere, or at least this minimizes those chances.
|
||||||
ENV["VAGRANT_CWD"] = Tempdir.new.path
|
ENV["VAGRANT_CWD"] = Tempdir.new.path
|
||||||
|
|
||||||
|
# Set the dummy provider to the default for tests
|
||||||
|
ENV["VAGRANT_DEFAULT_PROVIDER"] = "dummy"
|
||||||
|
|
||||||
# Unset all host plugins so that we aren't executing subprocess things
|
# Unset all host plugins so that we aren't executing subprocess things
|
||||||
# to detect a host for every test.
|
# to detect a host for every test.
|
||||||
Vagrant.plugin("2").manager.registered.dup.each do |plugin|
|
Vagrant.plugin("2").manager.registered.dup.each do |plugin|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
require_relative "../../../../base"
|
||||||
|
|
||||||
|
require Vagrant.source_root.join("plugins/synced_folders/rsync/command/rsync")
|
||||||
|
|
||||||
|
describe VagrantPlugins::SyncedFolderRSync::Command::Rsync do
|
||||||
|
include_context "unit"
|
||||||
|
|
||||||
|
let(:argv) { [] }
|
||||||
|
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(:communicator) { double("comm") }
|
||||||
|
|
||||||
|
let(:synced_folders) { {} }
|
||||||
|
|
||||||
|
let(:helper_class) { VagrantPlugins::SyncedFolderRSync::RsyncHelper }
|
||||||
|
|
||||||
|
subject do
|
||||||
|
described_class.new(argv, iso_env).tap do |s|
|
||||||
|
s.stub(synced_folders: synced_folders)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
iso_env.machine_names.each do |name|
|
||||||
|
m = iso_env.machine(name, iso_env.default_provider)
|
||||||
|
m.stub(communicate: communicator)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#execute" do
|
||||||
|
context "with a single machine" do
|
||||||
|
let(:ssh_info) {{
|
||||||
|
private_key_path: [],
|
||||||
|
}}
|
||||||
|
|
||||||
|
let(:machine) { iso_env.machine(iso_env.machine_names[0], iso_env.default_provider) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
communicator.stub(ready?: true)
|
||||||
|
machine.stub(ssh_info: ssh_info)
|
||||||
|
|
||||||
|
synced_folders[:rsync] = [
|
||||||
|
[:one, {}],
|
||||||
|
[:two, {}],
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't sync if communicator isn't ready and exits with 1" do
|
||||||
|
communicator.stub(ready?: false)
|
||||||
|
|
||||||
|
helper_class.should_receive(:rsync_single).never
|
||||||
|
|
||||||
|
expect(subject.execute).to eql(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "rsyncs each folder and exits successfully" do
|
||||||
|
synced_folders[:rsync].each do |_, opts|
|
||||||
|
helper_class.should_receive(:rsync_single).
|
||||||
|
with(machine, ssh_info, opts).
|
||||||
|
ordered
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(subject.execute).to eql(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,130 @@
|
||||||
|
require_relative "../../../base"
|
||||||
|
|
||||||
|
require Vagrant.source_root.join("plugins/synced_folders/rsync/helper")
|
||||||
|
|
||||||
|
describe VagrantPlugins::SyncedFolderRSync::RsyncHelper 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(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
|
||||||
|
|
||||||
|
subject { described_class }
|
||||||
|
|
||||||
|
before do
|
||||||
|
machine.stub(guest: guest)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#rsync_single" do
|
||||||
|
let(:result) { Vagrant::Util::Subprocess::Result.new(0, "", "") }
|
||||||
|
|
||||||
|
let(:ssh_info) {{
|
||||||
|
private_key_path: [],
|
||||||
|
}}
|
||||||
|
let(:opts) {{
|
||||||
|
hostpath: "/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(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(machine, ssh_info, opts) }.
|
||||||
|
to raise_error(Vagrant::Errors::RSyncError)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "host and guest paths" do
|
||||||
|
it "syncs the hostpath to the guest path" do
|
||||||
|
opts[:hostpath] = "/foo"
|
||||||
|
opts[:guestpath] = "/bar"
|
||||||
|
|
||||||
|
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
||||||
|
expect(args[args.length - 3]).to eql("/foo")
|
||||||
|
expect(args[args.length - 2]).to include("/bar")
|
||||||
|
end
|
||||||
|
|
||||||
|
subject.rsync_single(machine, ssh_info, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "expands the hostpath relative to the root path" do
|
||||||
|
opts[:hostpath] = "foo"
|
||||||
|
opts[:guestpath] = "/bar"
|
||||||
|
|
||||||
|
hostpath_expanded = File.expand_path(opts[:hostpath], machine.env.root_path)
|
||||||
|
|
||||||
|
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
||||||
|
expect(args[args.length - 3]).to eql(hostpath_expanded)
|
||||||
|
expect(args[args.length - 2]).to include("/bar")
|
||||||
|
end
|
||||||
|
|
||||||
|
subject.rsync_single(machine, ssh_info, opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes within the root path" do
|
||||||
|
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
||||||
|
expect(args.last).to be_kind_of(Hash)
|
||||||
|
|
||||||
|
opts = args.last
|
||||||
|
expect(opts[:workdir]).to eql(machine.env.root_path.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
context "excluding files" do
|
||||||
|
it "excludes files if given as a string" do
|
||||||
|
opts[:exclude] = "foo"
|
||||||
|
|
||||||
|
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
||||||
|
index = args.find_index("foo")
|
||||||
|
expect(index).to be > 0
|
||||||
|
expect(args[index-1]).to eql("--exclude")
|
||||||
|
end
|
||||||
|
|
||||||
|
subject.rsync_single(machine, ssh_info, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "excludes multiple files" do
|
||||||
|
opts[:exclude] = ["foo", "bar"]
|
||||||
|
|
||||||
|
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
||||||
|
index = args.find_index("foo")
|
||||||
|
expect(index).to be > 0
|
||||||
|
expect(args[index-1]).to eql("--exclude")
|
||||||
|
|
||||||
|
index = args.find_index("bar")
|
||||||
|
expect(index).to be > 0
|
||||||
|
expect(args[index-1]).to eql("--exclude")
|
||||||
|
end
|
||||||
|
|
||||||
|
subject.rsync_single(machine, ssh_info, opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -16,6 +16,8 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do
|
||||||
let(:host) { double("host") }
|
let(:host) { double("host") }
|
||||||
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
|
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
|
||||||
|
|
||||||
|
let(:helper_class) { VagrantPlugins::SyncedFolderRSync::RsyncHelper }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
machine.env.stub(host: host)
|
machine.env.stub(host: host)
|
||||||
machine.stub(guest: guest)
|
machine.stub(guest: guest)
|
||||||
|
@ -55,7 +57,7 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do
|
||||||
]
|
]
|
||||||
|
|
||||||
folders.each do |_, opts|
|
folders.each do |_, opts|
|
||||||
subject.should_receive(:rsync_single).
|
helper_class.should_receive(:rsync_single).
|
||||||
with(machine, ssh_info, opts).
|
with(machine, ssh_info, opts).
|
||||||
ordered
|
ordered
|
||||||
end
|
end
|
||||||
|
@ -63,81 +65,4 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do
|
||||||
subject.enable(machine, folders, {})
|
subject.enable(machine, folders, {})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#rsync_single" do
|
|
||||||
let(:result) { Vagrant::Util::Subprocess::Result.new(0, "", "") }
|
|
||||||
|
|
||||||
let(:ssh_info) {{
|
|
||||||
private_key_path: [],
|
|
||||||
}}
|
|
||||||
let(:opts) { {} }
|
|
||||||
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(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(machine, ssh_info, opts) }.
|
|
||||||
to raise_error(Vagrant::Errors::RSyncError)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "executes within the root path" do
|
|
||||||
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
|
||||||
expect(args.last).to be_kind_of(Hash)
|
|
||||||
|
|
||||||
opts = args.last
|
|
||||||
expect(opts[:workdir]).to eql(machine.env.root_path.to_s)
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
context "excluding files" do
|
|
||||||
it "excludes files if given as a string" do
|
|
||||||
opts[:exclude] = "foo"
|
|
||||||
|
|
||||||
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
|
||||||
index = args.find_index("foo")
|
|
||||||
expect(index).to be > 0
|
|
||||||
expect(args[index-1]).to eql("--exclude")
|
|
||||||
end
|
|
||||||
|
|
||||||
subject.rsync_single(machine, ssh_info, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "excludes multiple files" do
|
|
||||||
opts[:exclude] = ["foo", "bar"]
|
|
||||||
|
|
||||||
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
|
||||||
index = args.find_index("foo")
|
|
||||||
expect(index).to be > 0
|
|
||||||
expect(args[index-1]).to eql("--exclude")
|
|
||||||
|
|
||||||
index = args.find_index("bar")
|
|
||||||
expect(index).to be > 0
|
|
||||||
expect(args[index-1]).to eql("--exclude")
|
|
||||||
end
|
|
||||||
|
|
||||||
subject.rsync_single(machine, ssh_info, opts)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -98,5 +98,16 @@ describe Vagrant::Action::Builtin::MixinSyncedFolders do
|
||||||
result.length.should == 1
|
result.length.should == 1
|
||||||
result[:default].length.should == 1
|
result[:default].length.should == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should scope hash override the settings" do
|
||||||
|
folders["root"] = {
|
||||||
|
hostpath: "foo",
|
||||||
|
type: "nfs",
|
||||||
|
nfs__foo: "bar",
|
||||||
|
}
|
||||||
|
|
||||||
|
result = subject.synced_folders(machine)
|
||||||
|
expect(result[:nfs]["root"][:foo]).to eql("bar")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -90,27 +90,5 @@ describe Vagrant::Action::Builtin::SyncedFolders do
|
||||||
|
|
||||||
order.should == [:prepare, :enable]
|
order.should == [:prepare, :enable]
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should scope hash override the settings" do
|
|
||||||
actual = nil
|
|
||||||
tracker = Class.new(impl(true, "good")) do
|
|
||||||
define_method(:prepare) do |machine, folders, opts|
|
|
||||||
actual = folders
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
plugins[:tracker] = [tracker, 15]
|
|
||||||
|
|
||||||
synced_folders["tracker"] = {
|
|
||||||
"root" => {
|
|
||||||
hostpath: "foo",
|
|
||||||
tracker__foo: "bar",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
subject.call(env)
|
|
||||||
|
|
||||||
actual["root"][:foo].should == "bar"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,3 +17,8 @@ Note that while you have to run a special command to list the non-primary
|
||||||
subcommands, you don't have to do anything special to actually _run_ the
|
subcommands, you don't have to do anything special to actually _run_ the
|
||||||
non-primary subcommands. They're executed just like any other subcommand:
|
non-primary subcommands. They're executed just like any other subcommand:
|
||||||
`vagrant COMMAND`.
|
`vagrant COMMAND`.
|
||||||
|
|
||||||
|
The list of non-primary commands is below. Click on any command to learn
|
||||||
|
more about it.
|
||||||
|
|
||||||
|
* [rsync](/v2/cli/rsync.html)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
page_title: "vagrant rsync - Command-Line Interface"
|
||||||
|
sidebar_current: "cli-rsync"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Rsync
|
||||||
|
|
||||||
|
**Command: `vagrant rsync`**
|
||||||
|
|
||||||
|
This command forces a resync of any
|
||||||
|
[rsync synced folders](/v2/synced-folders/rsync.html).
|
|
@ -44,7 +44,6 @@ end
|
||||||
|
|
||||||
## Re-Syncing
|
## Re-Syncing
|
||||||
|
|
||||||
The rsync sync is done only during a `vagrant up` or `vagrant reload`. It
|
The rsync sync is done only during a `vagrant up` or `vagrant reload`. Vagrant
|
||||||
is not currently possible to force a re-sync in any way other than reloading.
|
does not automatically listen for changes on the filesystem and resync them.
|
||||||
|
Resyncing can be forced with a call to [vagrant rsync](/v2/cli/rsync.html).
|
||||||
We plan on exposing a command to force a sync in a future version of Vagrant.
|
|
||||||
|
|
Loading…
Reference in New Issue