vagrant-reflect 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/vagrant-reflect/command/reflect.rb +43 -92
- data/lib/vagrant-reflect/util/syncer.rb +214 -0
- data/lib/vagrant-reflect/version.rb +1 -1
- data/templates/locales/en.yml +6 -6
- metadata +3 -3
- data/lib/vagrant-reflect/helper.rb +0 -169
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10bf068f0fcd1751185c72edc2b8a9d0f9d3fc62
|
4
|
+
data.tar.gz: 62751eb5164e9a8f7bfd1f9d8793d245a300de67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5639afa42e9dc1767a9a29978dbcbed82904fa70b079d12d3c72ee4bec3c93751ea1422ad8838911383426a14d7e56bfb0a1b241af353340f9603fd29366c91
|
7
|
+
data.tar.gz: 2fe41628e246d06af901be938cded207f5a635a627cf1844f2d3ffdbeeda2f47f8319f9898c9d0170734eed42e700217254e98b049d3ee78bcfbe3965e1e7ae5
|
@@ -6,7 +6,7 @@ require 'vagrant/action/builtin/mixin_synced_folders'
|
|
6
6
|
require 'vagrant/util/busy'
|
7
7
|
require 'vagrant/util/platform'
|
8
8
|
|
9
|
-
require_relative '../
|
9
|
+
require_relative '../util/syncer'
|
10
10
|
|
11
11
|
require 'driskell-listen'
|
12
12
|
|
@@ -74,29 +74,30 @@ module VagrantReflect
|
|
74
74
|
folders = cached[:rsync]
|
75
75
|
next if !folders || folders.empty?
|
76
76
|
|
77
|
-
# Get the SSH info for this machine so we can do an initial
|
78
|
-
# sync to the VM.
|
79
|
-
ssh_info = machine.ssh_info
|
80
|
-
if ssh_info
|
81
|
-
machine.ui.info(
|
82
|
-
I18n.t('vagrant.plugins.vagrant-reflect.rsync_auto_initial'))
|
83
|
-
folders.each do |_, folder_opts|
|
84
|
-
SyncHelper.sync_single(machine, ssh_info, folder_opts)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
77
|
folders.each do |id, folder_opts|
|
89
78
|
# If we marked this folder to not auto sync, then
|
90
79
|
# don't do it.
|
91
80
|
next if folder_opts.key?(:auto) && !folder_opts[:auto]
|
92
81
|
|
82
|
+
# Push on .vagrant exclude
|
83
|
+
folder_opts = folder_opts.dup
|
84
|
+
folder_opts[:exclude] ||= []
|
85
|
+
folder_opts[:exclude] << '.vagrant/'
|
86
|
+
|
87
|
+
syncer = Syncer.new(machine, folder_opts)
|
88
|
+
|
89
|
+
machine.ui.info(
|
90
|
+
I18n.t('vagrant.plugins.vagrant-reflect.rsync_auto_initial'))
|
91
|
+
syncer.sync_full
|
92
|
+
|
93
93
|
hostpath = folder_opts[:hostpath]
|
94
94
|
hostpath = File.expand_path(hostpath, machine.env.root_path)
|
95
95
|
paths[hostpath] ||= []
|
96
96
|
paths[hostpath] << {
|
97
|
-
id:
|
97
|
+
id: id,
|
98
98
|
machine: machine,
|
99
|
-
opts: folder_opts
|
99
|
+
opts: folder_opts,
|
100
|
+
syncer: syncer
|
100
101
|
}
|
101
102
|
end
|
102
103
|
end
|
@@ -124,10 +125,10 @@ module VagrantReflect
|
|
124
125
|
'vagrant.plugins.vagrant-reflect.rsync_auto_path',
|
125
126
|
path: path.to_s))
|
126
127
|
|
127
|
-
next unless path_opts[:exclude]
|
128
|
+
next unless path_opts[:opts][:exclude]
|
128
129
|
|
129
|
-
Array(path_opts[:exclude]).each do |pattern|
|
130
|
-
ignores <<
|
130
|
+
Array(path_opts[:opts][:exclude]).each do |pattern|
|
131
|
+
ignores << Syncer.exclude_to_regexp(pattern.to_s)
|
131
132
|
end
|
132
133
|
end
|
133
134
|
|
@@ -171,13 +172,6 @@ module VagrantReflect
|
|
171
172
|
|
172
173
|
# Perform the sync for each machine
|
173
174
|
opts.each do |path_opts|
|
174
|
-
# Reload so we get the latest ID
|
175
|
-
path_opts[:machine].reload
|
176
|
-
if !path_opts[:machine].id || path_opts[:machine].id == ''
|
177
|
-
# Skip since we can't get SSH info without an ID
|
178
|
-
next
|
179
|
-
end
|
180
|
-
|
181
175
|
begin
|
182
176
|
# If we have any removals or have disabled incremental, perform a
|
183
177
|
# single full sync
|
@@ -185,25 +179,33 @@ module VagrantReflect
|
|
185
179
|
if !options[:incremental] || !removed.empty?
|
186
180
|
removed.each do |remove|
|
187
181
|
path_opts[:machine].ui.info(
|
188
|
-
I18n.t(
|
189
|
-
|
182
|
+
I18n.t(
|
183
|
+
'vagrant.plugins.vagrant-reflect.rsync_auto_full_remove',
|
184
|
+
path: strip_path(path, remove)))
|
190
185
|
end
|
191
186
|
|
192
187
|
[modified, added].each do |changes|
|
193
188
|
changes.each do |change|
|
194
189
|
path_opts[:machine].ui.info(
|
195
|
-
I18n.t(
|
196
|
-
|
190
|
+
I18n.t(
|
191
|
+
'vagrant.plugins.vagrant-reflect.rsync_auto_full_change',
|
192
|
+
path: strip_path(path, change)))
|
197
193
|
end
|
198
194
|
end
|
199
195
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
)
|
196
|
+
path_opts[:machine].ui.info(
|
197
|
+
I18n.t('vagrant.plugins.vagrant-reflect.rsync_auto_full'))
|
198
|
+
|
199
|
+
path_opts[:syncer].sync_full
|
205
200
|
elsif !modified.empty? || !added.empty?
|
206
|
-
|
201
|
+
# Pass the list of changes to rsync so we quickly synchronise only
|
202
|
+
# the changed files instead of the whole folder
|
203
|
+
items = strip_paths(path, modified + added)
|
204
|
+
path_opts[:syncer].sync_incremental(items) do |item|
|
205
|
+
path_opts[:machine].ui.info(
|
206
|
+
I18n.t('vagrant.plugins.vagrant-reflect.rsync_auto_increment',
|
207
|
+
path: item))
|
208
|
+
end
|
207
209
|
end
|
208
210
|
|
209
211
|
path_opts[:machine].ui.info(
|
@@ -215,70 +217,19 @@ module VagrantReflect
|
|
215
217
|
I18n.t('vagrant.plugins.vagrant-reflect.'\
|
216
218
|
'rsync_communicator_not_ready_callback'))
|
217
219
|
rescue Vagrant::Errors::VagrantError => e
|
218
|
-
path_opts[:machine].ui.error(e)
|
220
|
+
path_opts[:machine].ui.error(e.message)
|
219
221
|
end
|
220
222
|
end
|
221
223
|
end
|
222
224
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
line = sets[0].pop
|
228
|
-
sets.shift while !sets.empty? && sets[0].empty?
|
229
|
-
line[path.length..line.length] + "\n"
|
225
|
+
def strip_paths(path, items)
|
226
|
+
items.map do |item|
|
227
|
+
item[path.length..-1]
|
228
|
+
end
|
230
229
|
end
|
231
230
|
|
232
|
-
def
|
233
|
-
|
234
|
-
sets.shift while sets[0].empty?
|
235
|
-
line = false
|
236
|
-
|
237
|
-
# Pass the list of changes to rsync so we quickly synchronise only
|
238
|
-
# the changed files instead of the whole folder
|
239
|
-
SyncHelper.sync_single(
|
240
|
-
path_opts[:machine],
|
241
|
-
path_opts[:machine].ssh_info,
|
242
|
-
path_opts[:opts].merge(from_stdin: true)
|
243
|
-
) do |what, io|
|
244
|
-
next if what != :stdin
|
245
|
-
|
246
|
-
if line.nil?
|
247
|
-
io.close_write
|
248
|
-
next
|
249
|
-
end
|
250
|
-
|
251
|
-
begin
|
252
|
-
loop do
|
253
|
-
# If we don't have a line, grab one and print it
|
254
|
-
unless line
|
255
|
-
line = next_change(sets, path)
|
256
|
-
path_opts[:machine].ui.info(
|
257
|
-
I18n.t('vagrant.plugins.vagrant-reflect.rsync_auto_increment',
|
258
|
-
path: line))
|
259
|
-
end
|
260
|
-
|
261
|
-
# Handle partial writes
|
262
|
-
n = io.write_nonblock(line)
|
263
|
-
if n < line.length
|
264
|
-
line = line[n..line.length]
|
265
|
-
break
|
266
|
-
end
|
267
|
-
|
268
|
-
# When we've finished giving rsync the file list, set line to nil
|
269
|
-
# and return - on the next notify we will EOT stdin
|
270
|
-
if sets.empty?
|
271
|
-
line = nil
|
272
|
-
break
|
273
|
-
end
|
274
|
-
|
275
|
-
# Request a new line for next write
|
276
|
-
line = false
|
277
|
-
end
|
278
|
-
rescue IO::WaitWritable, Errno::EINTR
|
279
|
-
# Ignore
|
280
|
-
end
|
281
|
-
end
|
231
|
+
def strip_path(path, item)
|
232
|
+
item[path.length..-1]
|
282
233
|
end
|
283
234
|
end
|
284
235
|
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'vagrant/util/platform'
|
2
|
+
|
3
|
+
require_relative '../patched/subprocess'
|
4
|
+
|
5
|
+
module VagrantReflect
|
6
|
+
# This is a helper that abstracts out the functionality of rsyncing
|
7
|
+
# folders so that it can be called from anywhere.
|
8
|
+
class Syncer
|
9
|
+
# This converts an rsync exclude pattern to a regular expression
|
10
|
+
# we can send to Listen.
|
11
|
+
def self.exclude_to_regexp(exclude)
|
12
|
+
start_anchor = false
|
13
|
+
dir_only = false
|
14
|
+
|
15
|
+
if exclude.start_with?('/')
|
16
|
+
start_anchor = true
|
17
|
+
exclude = exclude[1..-1]
|
18
|
+
end
|
19
|
+
|
20
|
+
if exclude.end_with?('/')
|
21
|
+
dir_only = true
|
22
|
+
exclude = exclude[0..-2]
|
23
|
+
end
|
24
|
+
|
25
|
+
regexp = start_anchor ? '^' : '(?:^|/)'
|
26
|
+
|
27
|
+
# This is REALLY ghetto, but its a start. We can improve and
|
28
|
+
# keep unit tests passing in the future.
|
29
|
+
# TODO: Escaped wildcards get substituted incorrectly - replace with FSM?
|
30
|
+
exclude = exclude.gsub('.', '\\.')
|
31
|
+
exclude = exclude.gsub('***', '|||EMPTY|||')
|
32
|
+
exclude = exclude.gsub('**', '|||GLOBAL|||')
|
33
|
+
exclude = exclude.gsub('*', '|||PATH|||')
|
34
|
+
exclude = exclude.gsub('?', '[^/]')
|
35
|
+
exclude = exclude.gsub('|||PATH|||', '[^/]+')
|
36
|
+
exclude = exclude.gsub('|||GLOBAL|||', '.+')
|
37
|
+
exclude = exclude.gsub('|||EMPTY|||', '.*')
|
38
|
+
regexp += exclude
|
39
|
+
|
40
|
+
regexp += dir_only ? '/' : '(?:/|$)'
|
41
|
+
|
42
|
+
Regexp.new(regexp)
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(machine, opts)
|
46
|
+
@opts = opts
|
47
|
+
@machine = machine
|
48
|
+
@workdir = @machine.env.root_path.to_s
|
49
|
+
|
50
|
+
# Folder info
|
51
|
+
@guestpath = @opts[:guestpath]
|
52
|
+
@hostpath = @opts[:hostpath]
|
53
|
+
@hostpath = File.expand_path(@hostpath, machine.env.root_path)
|
54
|
+
@hostpath = Vagrant::Util::Platform.fs_real_path(@hostpath).to_s
|
55
|
+
|
56
|
+
if Vagrant::Util::Platform.windows?
|
57
|
+
# rsync for Windows expects cygwin style paths, always.
|
58
|
+
@hostpath = Vagrant::Util::Platform.cygwin_path(@hostpath)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Make sure the host path ends with a "/" to avoid creating
|
62
|
+
# a nested directory...
|
63
|
+
@hostpath += '/' unless @hostpath.end_with?('/')
|
64
|
+
|
65
|
+
# Connection information
|
66
|
+
username = @machine.ssh_info[:username]
|
67
|
+
host = @machine.ssh_info[:host]
|
68
|
+
proxy_command = ''
|
69
|
+
if @machine.ssh_info[:proxy_command]
|
70
|
+
proxy_command = "-o ProxyCommand='#{@machine.ssh_info[:proxy_command]}' "
|
71
|
+
end
|
72
|
+
|
73
|
+
rsh = [
|
74
|
+
"ssh -p #{@machine.ssh_info[:port]} " +
|
75
|
+
proxy_command +
|
76
|
+
'-o StrictHostKeyChecking=no '\
|
77
|
+
'-o IdentitiesOnly=true '\
|
78
|
+
'-o UserKnownHostsFile=/dev/null',
|
79
|
+
@machine.ssh_info[:private_key_path].map { |p| "-i '#{p}'" }
|
80
|
+
].flatten.join(' ')
|
81
|
+
|
82
|
+
@target = "#{username}@#{host}:#{@guestpath}"
|
83
|
+
|
84
|
+
# Exclude some files by default, and any that might be configured
|
85
|
+
# by the user.
|
86
|
+
excludes = []
|
87
|
+
excludes += Array(@opts[:exclude]).map(&:to_s) if @opts[:exclude]
|
88
|
+
excludes.uniq!
|
89
|
+
|
90
|
+
# Get the command-line arguments
|
91
|
+
@command = ['rsync']
|
92
|
+
@command += Array(@opts[:args]).dup if @opts[:args]
|
93
|
+
@command ||= ['--verbose', '--archive', '--delete', '-z', '--copy-links']
|
94
|
+
|
95
|
+
# On Windows, we have to set a default chmod flag to avoid permission
|
96
|
+
# issues
|
97
|
+
if Vagrant::Util::Platform.windows?
|
98
|
+
unless @command.any? { |arg| arg.start_with?('--chmod=') }
|
99
|
+
# Ensures that all non-masked bits get enabled
|
100
|
+
@command << '--chmod=ugo=rwX'
|
101
|
+
|
102
|
+
# Remove the -p option if --archive is enabled (--archive equals
|
103
|
+
# -rlptgoD) otherwise new files will not have the destination-default
|
104
|
+
# permissions
|
105
|
+
@command << '--no-perms' if
|
106
|
+
@command.include?('--archive') || @command.include?('-a')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Disable rsync's owner/group preservation (implied by --archive) unless
|
111
|
+
# specifically requested, since we adjust owner/group to match shared
|
112
|
+
# folder setting ourselves.
|
113
|
+
@command << '--no-owner' unless
|
114
|
+
@command.include?('--owner') || @command.include?('-o')
|
115
|
+
@command << '--no-group' unless
|
116
|
+
@command.include?('--group') || @command.include?('-g')
|
117
|
+
|
118
|
+
# Tell local rsync how to invoke remote rsync with sudo
|
119
|
+
if @machine.guest.capability?(:rsync_command)
|
120
|
+
@command << '--rsync-path' << @machine.guest.capability(:rsync_command)
|
121
|
+
end
|
122
|
+
|
123
|
+
@command += [
|
124
|
+
'-e', rsh
|
125
|
+
]
|
126
|
+
|
127
|
+
excludes.map { |e| @command += ['--exclude', e] }
|
128
|
+
|
129
|
+
machine.ui.info(
|
130
|
+
I18n.t(
|
131
|
+
'vagrant.plugins.vagrant-reflect.rsync_folder_configuration',
|
132
|
+
guestpath: @guestpath,
|
133
|
+
hostpath: @hostpath))
|
134
|
+
if excludes.length > 1
|
135
|
+
machine.ui.info(
|
136
|
+
I18n.t(
|
137
|
+
'vagrant.plugins.vagrant-reflect.rsync_folder_excludes',
|
138
|
+
excludes: excludes.inspect))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def sync_incremental(items, &block)
|
143
|
+
command = @command.dup + [
|
144
|
+
'--files-from=-',
|
145
|
+
@hostpath,
|
146
|
+
@target,
|
147
|
+
{
|
148
|
+
workdir: @workdir,
|
149
|
+
notify: :stdin
|
150
|
+
}
|
151
|
+
]
|
152
|
+
|
153
|
+
current = false
|
154
|
+
r = Vagrant::Util::SubprocessPatched.execute(*command) do |what, io|
|
155
|
+
next if what != :stdin
|
156
|
+
|
157
|
+
current = process_items(io, items, current, &block)
|
158
|
+
end
|
159
|
+
|
160
|
+
check_exit command, r
|
161
|
+
end
|
162
|
+
|
163
|
+
def sync_full
|
164
|
+
command = @command.dup + [
|
165
|
+
@hostpath,
|
166
|
+
@target,
|
167
|
+
{
|
168
|
+
workdir: @workdir
|
169
|
+
}
|
170
|
+
]
|
171
|
+
|
172
|
+
r = Vagrant::Util::SubprocessPatched.execute(*command)
|
173
|
+
|
174
|
+
check_exit command, r
|
175
|
+
end
|
176
|
+
|
177
|
+
protected
|
178
|
+
|
179
|
+
def process_items(io, items, current, &block)
|
180
|
+
until items.empty?
|
181
|
+
# If we don't have a line, grab one and print it
|
182
|
+
if current === false
|
183
|
+
current = items.shift + "\n"
|
184
|
+
block.call(current) if block_given?
|
185
|
+
end
|
186
|
+
|
187
|
+
# Handle partial writes
|
188
|
+
n = io.write_nonblock(current)
|
189
|
+
if n < current.length
|
190
|
+
current = current[n..current.length]
|
191
|
+
break
|
192
|
+
end
|
193
|
+
|
194
|
+
# Request a new line for next write
|
195
|
+
current = false
|
196
|
+
end
|
197
|
+
|
198
|
+
# Finished! Close stdin
|
199
|
+
io.close_write
|
200
|
+
rescue IO::WaitWritable, Errno::EINTR
|
201
|
+
# Ignore
|
202
|
+
end
|
203
|
+
|
204
|
+
def check_exit(command, r)
|
205
|
+
return if r.exit_code == 0
|
206
|
+
|
207
|
+
raise Vagrant::Errors::RSyncError,
|
208
|
+
command: command.join(' '),
|
209
|
+
guestpath: @guestpath,
|
210
|
+
hostpath: @hostpath,
|
211
|
+
stderr: r.stderr
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
data/templates/locales/en.yml
CHANGED
@@ -16,20 +16,20 @@ en:
|
|
16
16
|
Watching: %{path}
|
17
17
|
rsync_auto_increment: |-
|
18
18
|
Sending change: %{path}
|
19
|
-
|
19
|
+
rsync_auto_full_change: |-
|
20
20
|
Processing change: %{path}
|
21
|
-
|
21
|
+
rsync_auto_full_remove: |-
|
22
22
|
Processing removal: %{path}
|
23
|
+
rsync_auto_full: |-
|
24
|
+
Performing full synchronisation due to removals
|
23
25
|
rsync_auto_synced: |-
|
24
26
|
Synchronization completed
|
25
27
|
rsync_communicator_not_ready_callback: |-
|
26
28
|
Failed to connect to remote machine. This is usually caused by the
|
27
29
|
machine rebooting or being halted. Please make sure the machine is
|
28
30
|
running, and modify a file to try again.
|
29
|
-
|
30
|
-
|
31
|
-
rsync_folder_changes: |-
|
32
|
-
Rsyncing changes only: %{hostpath} => %{guestpath}
|
31
|
+
rsync_folder_configuration: |-
|
32
|
+
Configuring rsync: %{hostpath} => %{guestpath}
|
33
33
|
rsync_folder_excludes: " - Exclude: %{excludes}"
|
34
34
|
rsync_proxy_machine: |-
|
35
35
|
The provider ('%{provider}') for the machine '%{name}' is
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-reflect
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Woods
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: driskell-listen
|
@@ -33,9 +33,9 @@ extra_rdoc_files: []
|
|
33
33
|
files:
|
34
34
|
- lib/vagrant-reflect.rb
|
35
35
|
- lib/vagrant-reflect/command/reflect.rb
|
36
|
-
- lib/vagrant-reflect/helper.rb
|
37
36
|
- lib/vagrant-reflect/patched/subprocess.rb
|
38
37
|
- lib/vagrant-reflect/plugin.rb
|
38
|
+
- lib/vagrant-reflect/util/syncer.rb
|
39
39
|
- lib/vagrant-reflect/version.rb
|
40
40
|
- templates/locales/en.yml
|
41
41
|
homepage: https://github.com/driskell/vagrant-reflect
|
@@ -1,169 +0,0 @@
|
|
1
|
-
require 'vagrant/util/platform'
|
2
|
-
|
3
|
-
require_relative 'patched/subprocess'
|
4
|
-
|
5
|
-
module VagrantReflect
|
6
|
-
# This is a helper that abstracts out the functionality of rsyncing
|
7
|
-
# folders so that it can be called from anywhere.
|
8
|
-
class SyncHelper
|
9
|
-
# This converts an rsync exclude pattern to a regular expression
|
10
|
-
# we can send to Listen.
|
11
|
-
def self.exclude_to_regexp(path, exclude)
|
12
|
-
start_anchor = false
|
13
|
-
|
14
|
-
if exclude.start_with?('/')
|
15
|
-
start_anchor = true
|
16
|
-
exclude = exclude[1..-1]
|
17
|
-
end
|
18
|
-
|
19
|
-
path = "#{path}/" unless path.end_with?('/')
|
20
|
-
regexp = "^#{Regexp.escape(path)}"
|
21
|
-
regexp += '.*' unless start_anchor
|
22
|
-
|
23
|
-
# This is REALLY ghetto, but its a start. We can improve and
|
24
|
-
# keep unit tests passing in the future.
|
25
|
-
exclude = exclude.gsub('**', '|||GLOBAL|||')
|
26
|
-
exclude = exclude.gsub('*', '|||PATH|||')
|
27
|
-
exclude = exclude.gsub('|||PATH|||', '[^/]*')
|
28
|
-
exclude = exclude.gsub('|||GLOBAL|||', '.*')
|
29
|
-
regexp += exclude
|
30
|
-
|
31
|
-
Regexp.new(regexp)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.sync_single(machine, ssh_info, opts, &block)
|
35
|
-
# Folder info
|
36
|
-
guestpath = opts[:guestpath]
|
37
|
-
hostpath = opts[:hostpath]
|
38
|
-
hostpath = File.expand_path(hostpath, machine.env.root_path)
|
39
|
-
hostpath = Vagrant::Util::Platform.fs_real_path(hostpath).to_s
|
40
|
-
|
41
|
-
if Vagrant::Util::Platform.windows?
|
42
|
-
# rsync for Windows expects cygwin style paths, always.
|
43
|
-
hostpath = Vagrant::Util::Platform.cygwin_path(hostpath)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Make sure the host path ends with a "/" to avoid creating
|
47
|
-
# a nested directory...
|
48
|
-
hostpath += '/' unless hostpath.end_with?('/')
|
49
|
-
|
50
|
-
# Folder options
|
51
|
-
opts[:owner] ||= ssh_info[:username]
|
52
|
-
opts[:group] ||= ssh_info[:username]
|
53
|
-
|
54
|
-
# Connection information
|
55
|
-
username = ssh_info[:username]
|
56
|
-
host = ssh_info[:host]
|
57
|
-
proxy_command = ''
|
58
|
-
if ssh_info[:proxy_command]
|
59
|
-
proxy_command = "-o ProxyCommand='#{ssh_info[:proxy_command]}' "
|
60
|
-
end
|
61
|
-
|
62
|
-
rsh = [
|
63
|
-
"ssh -p #{ssh_info[:port]} " +
|
64
|
-
proxy_command +
|
65
|
-
'-o StrictHostKeyChecking=no '\
|
66
|
-
'-o IdentitiesOnly=true '\
|
67
|
-
'-o UserKnownHostsFile=/dev/null',
|
68
|
-
ssh_info[:private_key_path].map { |p| "-i '#{p}'" }
|
69
|
-
].flatten.join(' ')
|
70
|
-
|
71
|
-
# Exclude some files by default, and any that might be configured
|
72
|
-
# by the user.
|
73
|
-
excludes = ['.vagrant/']
|
74
|
-
excludes += Array(opts[:exclude]).map(&:to_s) if opts[:exclude]
|
75
|
-
excludes.uniq!
|
76
|
-
|
77
|
-
# Get the command-line arguments
|
78
|
-
args = nil
|
79
|
-
args = Array(opts[:args]).dup if opts[:args]
|
80
|
-
args ||= ['--verbose', '--archive', '--delete', '-z', '--copy-links']
|
81
|
-
|
82
|
-
# On Windows, we have to set a default chmod flag to avoid permission
|
83
|
-
# issues
|
84
|
-
if Vagrant::Util::Platform.windows?
|
85
|
-
unless args.any? { |arg| arg.start_with?('--chmod=') }
|
86
|
-
# Ensures that all non-masked bits get enabled
|
87
|
-
args << '--chmod=ugo=rwX'
|
88
|
-
|
89
|
-
# Remove the -p option if --archive is enabled (--archive equals
|
90
|
-
# -rlptgoD) otherwise new files will not have the destination-default
|
91
|
-
# permissions
|
92
|
-
args << '--no-perms' if
|
93
|
-
args.include?('--archive') || args.include?('-a')
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# Disable rsync's owner/group preservation (implied by --archive) unless
|
98
|
-
# specifically requested, since we adjust owner/group to match shared
|
99
|
-
# folder setting ourselves.
|
100
|
-
args << '--no-owner' unless
|
101
|
-
args.include?('--owner') || args.include?('-o')
|
102
|
-
args << '--no-group' unless
|
103
|
-
args.include?('--group') || args.include?('-g')
|
104
|
-
|
105
|
-
# Tell local rsync how to invoke remote rsync with sudo
|
106
|
-
if machine.guest.capability?(:rsync_command)
|
107
|
-
args << '--rsync-path' << machine.guest.capability(:rsync_command)
|
108
|
-
end
|
109
|
-
|
110
|
-
args << '--files-from=-' if opts[:from_stdin] && block_given?
|
111
|
-
|
112
|
-
# Build up the actual command to execute
|
113
|
-
command = [
|
114
|
-
'rsync',
|
115
|
-
args,
|
116
|
-
'-e', rsh,
|
117
|
-
excludes.map { |e| ['--exclude', e] },
|
118
|
-
hostpath,
|
119
|
-
"#{username}@#{host}:#{guestpath}"
|
120
|
-
].flatten
|
121
|
-
|
122
|
-
# The working directory should be the root path
|
123
|
-
command_opts = {}
|
124
|
-
command_opts[:workdir] = machine.env.root_path.to_s
|
125
|
-
command_opts[:notify] = [:stdin] if opts[:from_stdin] && block_given?
|
126
|
-
|
127
|
-
if opts[:from_stdin] && block_given?
|
128
|
-
machine.ui.info(
|
129
|
-
I18n.t(
|
130
|
-
'vagrant.plugins.vagrant-reflect.rsync_folder_changes',
|
131
|
-
guestpath: guestpath,
|
132
|
-
hostpath: hostpath))
|
133
|
-
else
|
134
|
-
machine.ui.info(
|
135
|
-
I18n.t(
|
136
|
-
'vagrant.plugins.vagrant-reflect.rsync_folder',
|
137
|
-
guestpath: guestpath,
|
138
|
-
hostpath: hostpath))
|
139
|
-
end
|
140
|
-
if excludes.length > 1
|
141
|
-
machine.ui.info(
|
142
|
-
I18n.t(
|
143
|
-
'vagrant.plugins.vagrant-reflect.rsync_folder_excludes',
|
144
|
-
excludes: excludes.inspect))
|
145
|
-
end
|
146
|
-
|
147
|
-
# If we have tasks to do before rsyncing, do those.
|
148
|
-
if machine.guest.capability?(:rsync_pre)
|
149
|
-
machine.guest.capability(:rsync_pre, opts)
|
150
|
-
end
|
151
|
-
|
152
|
-
r = Vagrant::Util::SubprocessPatched.execute(*(command + [command_opts]), &block)
|
153
|
-
if r.exit_code != 0
|
154
|
-
raise Vagrant::Errors::RSyncError,
|
155
|
-
command: command.join(' '),
|
156
|
-
guestpath: guestpath,
|
157
|
-
hostpath: hostpath,
|
158
|
-
stderr: r.stderr
|
159
|
-
end
|
160
|
-
|
161
|
-
# If we have tasks to do after rsyncing, do those.
|
162
|
-
# REMOVE THESE - it triggers for VirtualBox an expensive find command that
|
163
|
-
# changes ownership, but we don't believe this is necessary
|
164
|
-
# if machine.guest.capability?(:rsync_post)
|
165
|
-
# machine.guest.capability(:rsync_post, opts)
|
166
|
-
# end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|