Merge pull request #7726 from chrisroberts/fix/rsync-exclude

Ignore files excluded from sync on chown
This commit is contained in:
Chris Roberts 2016-08-19 09:58:31 -07:00 committed by GitHub
commit a7537a6be0
11 changed files with 169 additions and 130 deletions

View File

@ -1,33 +1,10 @@
require "shellwords"
require_relative "../../../synced_folders/rsync/default_unix_cap"
module VagrantPlugins
module GuestDarwin
module Cap
class RSync
def self.rsync_installed(machine)
machine.communicate.test("which rsync")
end
def self.rsync_command(machine)
"sudo rsync"
end
def self.rsync_pre(machine, opts)
guest_path = Shellwords.escape(opts[:guestpath])
machine.communicate.sudo("mkdir -p #{guest_path}")
end
def self.rsync_post(machine, opts)
if opts.key?(:chown) && !opts[:chown]
return
end
guest_path = Shellwords.escape(opts[:guestpath])
machine.communicate.sudo(
"find #{guest_path} '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " +
"xargs -0 chown #{opts[:owner]}:#{opts[:group]}")
end
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
end
end
end

View File

@ -1,37 +1,14 @@
require "shellwords"
require_relative "../../../synced_folders/rsync/default_unix_cap"
module VagrantPlugins
module GuestFreeBSD
module Cap
class RSync
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
def self.rsync_install(machine)
machine.communicate.sudo("pkg install -y rsync")
end
def self.rsync_installed(machine)
machine.communicate.test("which rsync")
end
def self.rsync_command(machine)
"sudo rsync"
end
def self.rsync_pre(machine, opts)
guest_path = Shellwords.escape(opts[:guestpath])
machine.communicate.sudo("mkdir -p #{guest_path}")
end
def self.rsync_post(machine, opts)
if opts.key?(:chown) && !opts[:chown]
return
end
guest_path = Shellwords.escape(opts[:guestpath])
machine.communicate.sudo(
"find #{guest_path} '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " +
"xargs -0 -r chown #{opts[:owner]}:#{opts[:group]}")
end
end
end
end

View File

@ -1,35 +1,10 @@
require "shellwords"
require_relative "../../../synced_folders/rsync/default_unix_cap"
module VagrantPlugins
module GuestLinux
module Cap
class RSync
def self.rsync_installed(machine)
machine.communicate.test("which rsync")
end
def self.rsync_command(machine)
"sudo rsync"
end
def self.rsync_pre(machine, opts)
guest_path = Shellwords.escape(opts[:guestpath])
machine.communicate.sudo("mkdir -p #{guest_path}")
end
def self.rsync_post(machine, opts)
if opts.key?(:chown) && !opts[:chown]
return
end
guest_path = Shellwords.escape(opts[:guestpath])
machine.communicate.sudo(
"find #{guest_path} " +
"'!' -type l -a " +
"'(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " +
"xargs -0 -r chown #{opts[:owner]}:#{opts[:group]}")
end
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
end
end
end

View File

@ -1,10 +1,10 @@
require_relative "../../../synced_folders/rsync/default_unix_cap"
module VagrantPlugins
module GuestNetBSD
module Cap
class RSync
def self.rsync_installed(machine)
machine.communicate.test("which rsync")
end
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
def self.rsync_install(machine)
machine.communicate.sudo(
@ -12,22 +12,6 @@ module VagrantPlugins
'`uname -m`/`uname -r | cut -d. -f1-2`/All" ' \
'pkg_add rsync')
end
def self.rsync_command(machine)
"sudo rsync"
end
def self.rsync_pre(machine, opts)
machine.communicate.tap do |comm|
comm.sudo("mkdir -p '#{opts[:guestpath]}'")
end
end
def self.rsync_post(machine, opts)
machine.communicate.sudo(
"find '#{opts[:guestpath]}' '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " +
"xargs -0 -r chown #{opts[:owner]}:#{opts[:group]}")
end
end
end
end

View File

@ -1,33 +1,17 @@
require_relative "../../../synced_folders/rsync/default_unix_cap"
module VagrantPlugins
module GuestOpenBSD
module Cap
class RSync
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
def self.rsync_install(machine)
machine.communicate.sudo(
'PKG_PATH="http://ftp.openbsd.org/pub/OpenBSD/' \
'`uname -r`/packages/`arch -s`/" ' \
'pkg_add -I rsync--')
end
def self.rsync_installed(machine)
machine.communicate.test("which rsync")
end
def self.rsync_command(machine)
"sudo rsync"
end
def self.rsync_pre(machine, opts)
machine.communicate.tap do |comm|
comm.sudo("mkdir -p '#{opts[:guestpath]}'")
end
end
def self.rsync_post(machine, opts)
machine.communicate.sudo(
"find '#{opts[:guestpath]}' '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " +
"xargs -0 -r chown #{opts[:owner]}:#{opts[:group]}")
end
end
end
end

View File

@ -1,7 +1,11 @@
require_relative "../../../synced_folders/rsync/default_unix_cap"
module VagrantPlugins
module GuestSmartos
module Cap
class RSync
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
def self.rsync_installed(machine)
machine.communicate.test("which rsync")
end
@ -17,8 +21,11 @@ module VagrantPlugins
end
def self.rsync_post(machine, opts)
machine.communicate.execute("#{machine.config.smartos.suexec_cmd} find '#{opts[:guestpath]}' '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " +
"#{machine.config.smartos.suexec_cmd} xargs -0 chown #{opts[:owner]}:#{opts[:group]}")
if opts.key?(:chown) && !opts[:chown]
return
end
suexec_cmd = machine.config.smartos.suexec_cmd
machine.communicate.execute("#{suexec_cmd} #{build_rsync_chown(opts)}")
end
end
end

View File

@ -1,7 +1,11 @@
require_relative "../../../synced_folders/rsync/default_unix_cap"
module VagrantPlugins
module GuestSolaris
module Cap
class RSync
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
def self.rsync_installed(machine)
machine.communicate.test("which rsync")
end
@ -17,10 +21,11 @@ module VagrantPlugins
end
def self.rsync_post(machine, opts)
if opts.key?(:chown) && !opts[:chown]
return
end
suexec_cmd = machine.config.solaris.suexec_cmd
machine.communicate.execute(
"#{suexec_cmd} find '#{opts[:guestpath]}' '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " +
"xargs -0 chown #{opts[:owner]}:#{opts[:group]}")
machine.communicate.execute("#{suexec_cmd} #{build_rsync_chown(opts)}")
end
end
end

View File

@ -1,10 +1,10 @@
require_relative "../../../synced_folders/rsync/default_unix_cap"
module VagrantPlugins
module GuestSolaris11
module Cap
class RSync
def self.rsync_installed(machine)
machine.communicate.test("which rsync")
end
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
def self.rsync_command(machine)
"#{machine.config.solaris11.suexec_cmd} rsync"
@ -17,10 +17,11 @@ module VagrantPlugins
end
def self.rsync_post(machine, opts)
if opts.key?(:chown) && !opts[:chown]
return
end
suexec_cmd = machine.config.solaris11.suexec_cmd
machine.communicate.execute(
"#{suexec_cmd} '#{opts[:guestpath]}' '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " +
"xargs -0 chown #{opts[:owner]}:#{opts[:group]}")
machine.communicate.execute("#{suexec_cmd} #{build_rsync_chown(opts)}")
end
end
end

View File

@ -0,0 +1,45 @@
require "shellwords"
module VagrantPlugins
module SyncedFolderRSync
# This module provides default rsync capabilities for
# unix type operating systems.
module DefaultUnixCap
def rsync_installed(machine)
machine.communicate.test("which rsync")
end
def rsync_command(machine)
"sudo rsync"
end
def rsync_pre(machine, opts)
guest_path = Shellwords.escape(opts[:guestpath])
machine.communicate.sudo("mkdir -p #{guest_path}")
end
def rsync_post(machine, opts)
if opts.key?(:chown) && !opts[:chown]
return
end
machine.communicate.sudo(build_rsync_chown(opts))
end
def build_rsync_chown(opts)
guest_path = Shellwords.escape(opts[:guestpath])
if(opts[:exclude])
exclude_base = Pathname.new(opts[:guestpath])
exclusions = Array(opts[:exclude]).map do |ex_path|
ex_path = ex_path.slice(1, ex_path.size) if ex_path.start_with?(File::SEPARATOR)
"-path #{exclude_base.join(ex_path)} -prune"
end.join(" -o ") + " -o "
end
"find #{guest_path} #{exclusions}" \
"'!' -type l -a " \
"'(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -exec " \
"chown #{opts[:owner]}:#{opts[:group]} '{}' +"
end
end
end
end

View File

@ -0,0 +1,85 @@
require_relative "../../../../base"
describe "VagrantPlugins::GuestLinux::Cap::Rsync" do
let(:caps) do
VagrantPlugins::GuestLinux::Plugin
.components
.guest_capabilities[:linux]
end
let(:machine) { double("machine") }
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
let(:guest_directory){ "/guest/directory/path" }
before do
allow(machine).to receive(:communicate).and_return(comm)
end
after do
comm.verify_expectations!
end
describe ".rsync_installed" do
let(:cap) { caps.get(:rsync_installed) }
it "checks if the command is installed" do
comm.expect_command("which rsync")
cap.rsync_installed(machine)
end
end
describe ".rsync_command" do
let(:cap) { caps.get(:rsync_command) }
it "provides the rsync command to use" do
expect(cap.rsync_command(machine)).to eq("sudo rsync")
end
end
describe ".rsync_pre" do
let(:cap) { caps.get(:rsync_pre) }
it "creates target directory on guest" do
comm.expect_command("mkdir -p #{guest_directory}")
cap.rsync_pre(machine, :guestpath => guest_directory)
end
end
describe ".rsync_post" do
let(:cap) { caps.get(:rsync_post) }
let(:host_directory){ '.' }
let(:owner) { "vagrant-user" }
let(:group) { "vagrant-group" }
let(:excludes) { false }
let(:options) do
{
hostpath: host_directory,
guestpath: guest_directory,
owner: owner,
group: group,
exclude: excludes
}
end
it "chowns files within the guest directory" do
comm.expect_command(
"find #{guest_directory} '!' -type l -a '(' ! -user #{owner} -or " \
"! -group #{group} ')' -exec chown #{owner}:#{group} '{}' +"
)
cap.rsync_post(machine, options)
end
context "with excludes provided" do
let(:excludes){ ["tmp", "state/*"] }
it "ignores files that are excluded" do
comm.expect_command(
"find #{guest_directory} -path #{File.join(guest_directory, excludes.first)} -prune -o " \
"-path #{File.join(guest_directory, excludes.last)} -prune -o '!' -type l -a '(' ! -user " \
"#{owner} -or ! -group #{group} ')' -exec chown #{owner}:#{group} '{}' +"
)
cap.rsync_post(machine, options)
end
end
end
end

View File

@ -40,9 +40,8 @@ describe "VagrantPlugins::VagrantPlugins::Cap::Rsync" do
describe ".rsync_post" do
it 'chowns incorrectly owned files in sync dir' do
communicator.expect_command("pfexec find '/sync_dir' '(' ! -user somebody -or ! -group somegroup ')' -print0 | pfexec xargs -0 chown somebody:somegroup")
communicator.expect_command("pfexec find /sync_dir '!' -type l -a '(' ! -user somebody -or ! -group somegroup ')' -exec chown somebody:somegroup '{}' +")
plugin.rsync_post(machine, guestpath: '/sync_dir', owner: 'somebody', group: 'somegroup')
end
end
end