vagrant-mirror 0.1.0.alpha → 0.1.1.alpha
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.
- data/Gemfile.lock +1 -1
- data/README.md +60 -25
- data/lib/vagrant-mirror/middleware/sync.rb +3 -1
- data/lib/vagrant-mirror/version.rb +1 -1
- data/spec/vagrant-mirror/command_spec.rb +3 -2
- data/spec/vagrant-mirror/listener/host_spec.rb +6 -2
- data/spec/vagrant-mirror/middleware/mirror_spec.rb +3 -2
- data/spec/vagrant-mirror/middleware/sync_spec.rb +12 -3
- data/spec/vagrant-mirror/rsync_spec.rb +4 -4
- metadata +45 -18
- data/lib/vagrant-mirror/sync/all.rb +0 -60
- data/lib/vagrant-mirror/sync/base.rb +0 -98
- data/lib/vagrant-mirror/sync/changes.rb +0 -61
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Vagrant::Mirror
|
2
2
|
|
3
3
|
[](https://travis-ci.org/ingenerator/vagrant-mirror)
|
4
|
+
[](https://codeclimate.com/github/ingenerator/vagrant-mirror)
|
4
5
|
|
5
6
|
**This plugin is for the 1.0.x series of Vagrant and has not been updated to work with 1.1 and
|
6
7
|
above. We plan to update it eventually, if you want it faster than that then contributions are
|
@@ -18,29 +19,50 @@ number of dependencies.
|
|
18
19
|
|
19
20
|
## Installation
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
You need to install the plugin as a gem within Vagrant's embedded Ruby environment. You will
|
23
|
+
also require the appropriate listen filesystem driver to watch for changes. The plugin
|
24
|
+
currently only has an alpha release available, so you need to specify --pre on the install
|
25
|
+
command.
|
23
26
|
|
24
|
-
|
27
|
+
### On Windows
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
* For OS X - [rb-fsevent](https://github.com/thibaudgg/rb-fsevent)
|
29
|
+
On Windows, the [WDM](https://github.com/Maher4Ever/wdm) driver is recommended. Install like
|
30
|
+
this:
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
+
```bash
|
33
|
+
# Add the Ruby devkit to the Vagrant environment so that native extensions can build
|
34
|
+
# If your vagrant install path is different you will need to edit this command
|
35
|
+
c:\vagrant\vagrant\embedded\devkitvars.bat
|
32
36
|
|
33
|
-
|
37
|
+
# Install the latest alpha release of the vagrant-mirror gem
|
38
|
+
vagrant gem install vagrant-mirror --pre
|
34
39
|
|
35
|
-
|
36
|
-
|
40
|
+
# Install the wdm gem
|
41
|
+
vagrant gem install wdm
|
42
|
+
```
|
43
|
+
|
44
|
+
### On Linux
|
37
45
|
|
38
|
-
|
39
|
-
|
40
|
-
|
46
|
+
Vagrant-mirror is not tested on a linux host - though in theory it should work (the
|
47
|
+
specs run on Travis and all pass, and listen is tested cross-platform). The
|
48
|
+
[rb-inotify](https://github.com/nex3/rb-inotify) driver is recommended.
|
49
|
+
|
50
|
+
```bash
|
51
|
+
vagrant gem install vagrant-mirror --pre
|
52
|
+
vagrant gem install rb-inotify
|
41
53
|
```
|
42
54
|
|
43
|
-
|
55
|
+
If you have problems getting it working on linux, contributions are welcome.
|
56
|
+
|
57
|
+
### On OS X
|
58
|
+
|
59
|
+
Vagrant-mirror is not tested on OS X - though in theory it should work. The
|
60
|
+
[rb-fsevent](https://github.com/thibaudgg/rb-fsevent) driver is recommended.
|
61
|
+
|
62
|
+
```bash
|
63
|
+
vagrant gem install vagrant-mirror --pre
|
64
|
+
vagrant gem install rb-inotify
|
65
|
+
```
|
44
66
|
|
45
67
|
## Basic usage
|
46
68
|
|
@@ -55,10 +77,10 @@ Include paths to mirror in your Vagrantfile like so:
|
|
55
77
|
config.mirror.folder "foo", "/guest/mirror/path"
|
56
78
|
```
|
57
79
|
|
58
|
-
When you run `vagrant up` or `vagrant
|
80
|
+
When you run `vagrant up` or `vagrant reload`, vagrant-mirror will:
|
59
81
|
|
60
82
|
* Ensure that your guest has any shared folders required for the pair
|
61
|
-
* Create any local symlinks required
|
83
|
+
* Create any local symlinks required (see below)
|
62
84
|
* Run rsync on the guest to copy from the virtualbox shared folder to the local guest path
|
63
85
|
* Register with the local host filesystem for updates using using [listen](https://rubygems.org/gems/listen)
|
64
86
|
|
@@ -66,9 +88,9 @@ When changes are detected on the host, they will be notified by the listen gem.
|
|
66
88
|
detected, the host will trigger the guest to run rsync on the changed path to update the locally
|
67
89
|
stored file.
|
68
90
|
|
69
|
-
If you want to force a full resync, you can run `vagrant mirror
|
91
|
+
If you want to force a full resync, you can run `vagrant mirror sync`.
|
70
92
|
|
71
|
-
If for some reason the mirror crashes you can just run `vagrant
|
93
|
+
If for some reason the mirror crashes you can just run `vagrant mirror monitor` on the host to bring
|
72
94
|
it back up.
|
73
95
|
|
74
96
|
## Advanced usage
|
@@ -89,6 +111,11 @@ the virtualbox shared folder?
|
|
89
111
|
|
90
112
|
This will exclude the "/log" folder from rsync and symlink it directly to the shared folder.
|
91
113
|
|
114
|
+
Under the hood, vagrant-mirror just uses rsync so if for some reason you want to update your
|
115
|
+
host with a bigger set of changed files from the guest (perhaps you ran a script that modified
|
116
|
+
your source code somehow) you can just SSH to the guest and run rsync to copy files from the
|
117
|
+
mirror folder back to the virtualbox share.
|
118
|
+
|
92
119
|
### Excluding paths
|
93
120
|
|
94
121
|
Perhaps there are paths you don't require on your virtual machine. For example, syncing your docs
|
@@ -106,9 +133,9 @@ to the directory being mirrored.
|
|
106
133
|
|
107
134
|
### Propogating deletes
|
108
135
|
|
109
|
-
By default, vagrant mirror transfers new files and folders but does not propogate deletes.
|
110
|
-
lead to unwanted behaviour, in particular if your application on the guest indexes or
|
111
|
-
the files it finds. You can enable deletions with the following:
|
136
|
+
By default, vagrant mirror sync transfers new files and folders but does not propogate deletes.
|
137
|
+
This can lead to unwanted behaviour, in particular if your application on the guest indexes or
|
138
|
+
autoloads all the files it finds. You can enable deletions with the following:
|
112
139
|
|
113
140
|
```ruby
|
114
141
|
# To mirror the vagrant root path - the options hash is also available when sharing any folder
|
@@ -120,12 +147,18 @@ the files it finds. You can enable deletions with the following:
|
|
120
147
|
You should ensure that your "exclude" configuration includes all the paths that may be present on
|
121
148
|
the guest (build directories, cache, assets) as otherwise they will be deleted.
|
122
149
|
|
150
|
+
**Note that the :delete option only controls whether rsync will delete unexpected files during
|
151
|
+
vagrant mirror sync. During active mirroring, if you delete a file on the host this will be
|
152
|
+
detected by listen and the file will be deleted on the guest.**
|
153
|
+
|
123
154
|
### Notifications
|
124
155
|
|
125
156
|
The time between updates is generally pretty fast, but it is nonzero. If you're working in fast
|
126
157
|
cycles it can be that you rerun a command on the guest before your updated files have been
|
127
158
|
transferred, which may be confusing. Avoid this by having vagrant-mirror issue a system beep whenever
|
128
|
-
transfers complete.
|
159
|
+
transfers complete. Note that every so often vagrant will drop the SSH connection and the first
|
160
|
+
command on a new connection can take at least 4 seconds, subsequent commands should be significantly
|
161
|
+
faster.
|
129
162
|
|
130
163
|
```ruby
|
131
164
|
# To mirror the vagrant root path - the options hash is also available when sharing any folder
|
@@ -138,14 +171,16 @@ transfers complete.
|
|
138
171
|
|
139
172
|
1. Fork it
|
140
173
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
141
|
-
3. Commit your changes (`git commit -am 'Add some feature'`) with specs
|
174
|
+
3. Commit your changes (`git commit -am 'Add some feature'`) with specs. Changes without specs will
|
175
|
+
not be merged.
|
142
176
|
4. Push to the branch (`git push origin my-new-feature`)
|
143
177
|
5. Create new Pull Request
|
144
178
|
|
145
179
|
## Acknowledgements
|
146
180
|
|
147
181
|
The [vagrant-notify](https://github.com/fgrehm/vagrant-notify/) plugin was very useful in working
|
148
|
-
out how to structure this plugin.
|
182
|
+
out how to structure this plugin. And of course, none of this would be possible without the great
|
183
|
+
work on vagrant itself, thanks to Mitchell for that.
|
149
184
|
|
150
185
|
## Copyright
|
151
186
|
|
@@ -42,7 +42,9 @@ module Vagrant
|
|
42
42
|
ui.info("Synchronising for #{host_path}")
|
43
43
|
|
44
44
|
# Create any required symlinks
|
45
|
-
mirror_config[:symlinks].each do |
|
45
|
+
mirror_config[:symlinks].each do | origpath |
|
46
|
+
# Copy the path so that it is not altered elsewhere, then strip any leading /
|
47
|
+
relpath = origpath.dup
|
46
48
|
relpath.sub!(/^\//, '')
|
47
49
|
source = "#{guest_sf_path}/#{relpath}"
|
48
50
|
target = "#{mirror_config[:guest_path]}/#{relpath}"
|
@@ -10,9 +10,10 @@ describe Vagrant::Mirror::Command do
|
|
10
10
|
env.stub(:ui).and_return ui
|
11
11
|
end
|
12
12
|
|
13
|
-
subject { Vagrant::Mirror::Command.new(argv, env) }
|
14
|
-
|
15
13
|
describe "#execute" do
|
14
|
+
|
15
|
+
subject { Vagrant::Mirror::Command.new(argv, env) }
|
16
|
+
|
16
17
|
shared_examples "cannot run in multivm" do
|
17
18
|
before (:each) do
|
18
19
|
env.stub(:multivm?).and_return(true)
|
@@ -2,13 +2,14 @@ describe Vagrant::Mirror::Listener::Host do
|
|
2
2
|
|
3
3
|
let (:queue) { double("Queue").as_null_object }
|
4
4
|
|
5
|
-
subject { Vagrant::Mirror::Listener::Host.new('c:/host', queue) }
|
6
|
-
|
7
5
|
before (:each) do
|
8
6
|
Listen.stub(:to).as_null_object
|
9
7
|
end
|
10
8
|
|
11
9
|
describe "#listen!" do
|
10
|
+
|
11
|
+
subject { Vagrant::Mirror::Listener::Host.new('c:/host', queue) }
|
12
|
+
|
12
13
|
it "listens to the host directory" do
|
13
14
|
Listen.should_receive(:to).with('c:/host', anything())
|
14
15
|
|
@@ -71,6 +72,9 @@ describe Vagrant::Mirror::Listener::Host do
|
|
71
72
|
end
|
72
73
|
|
73
74
|
describe "#listen" do
|
75
|
+
|
76
|
+
subject { Vagrant::Mirror::Listener::Host.new('c:/host', queue) }
|
77
|
+
|
74
78
|
let (:thread) { double("Thread") }
|
75
79
|
|
76
80
|
before (:each) do
|
@@ -33,9 +33,10 @@ describe Vagrant::Mirror::Middleware::Mirror do
|
|
33
33
|
queue.stub(:pop).and_return({ :quit => true})
|
34
34
|
end
|
35
35
|
|
36
|
-
subject { Vagrant::Mirror::Middleware::Mirror.new(app, env) }
|
37
|
-
|
38
36
|
describe "#call" do
|
37
|
+
|
38
|
+
subject { Vagrant::Mirror::Middleware::Mirror.new(app, env) }
|
39
|
+
|
39
40
|
shared_examples "chained mirror middleware" do
|
40
41
|
it "calls the next middleware" do
|
41
42
|
app.should_receive(:call).with(env)
|
@@ -28,10 +28,10 @@ describe Vagrant::Mirror::Middleware::Sync do
|
|
28
28
|
|
29
29
|
end
|
30
30
|
|
31
|
-
subject { Vagrant::Mirror::Middleware::Sync.new(app, env) }
|
32
|
-
|
33
31
|
describe "#call" do
|
34
32
|
|
33
|
+
subject { Vagrant::Mirror::Middleware::Sync.new(app, env) }
|
34
|
+
|
35
35
|
shared_examples "chained middleware" do
|
36
36
|
it "calls the next middleware" do
|
37
37
|
app.should_receive(:call).with(env)
|
@@ -114,7 +114,7 @@ describe Vagrant::Mirror::Middleware::Sync do
|
|
114
114
|
let (:host_path) { File.join(Dir.pwd, 'logs') }
|
115
115
|
|
116
116
|
before (:each) do
|
117
|
-
config.mirror.vagrant_root "/var/vagrant", { :symlinks => ['logs'] }
|
117
|
+
config.mirror.vagrant_root "/var/vagrant", { :symlinks => ['/logs'] }
|
118
118
|
config.vm.share_folder("v-root", "/vagrant", ".")
|
119
119
|
|
120
120
|
File.stub(:exists?).with(host_path).and_return true
|
@@ -137,6 +137,15 @@ describe Vagrant::Mirror::Middleware::Sync do
|
|
137
137
|
|
138
138
|
subject.call(env)
|
139
139
|
end
|
140
|
+
|
141
|
+
it "does not modify the excludes config passed to rsync" do
|
142
|
+
Vagrant::Mirror::Rsync.should_receive(:new)
|
143
|
+
.with(anything, anything, anything, hash_including({ :exclude => [ '/logs' ]}))
|
144
|
+
.and_return(rsync)
|
145
|
+
|
146
|
+
subject.call(env)
|
147
|
+
end
|
148
|
+
|
140
149
|
end
|
141
150
|
|
142
151
|
context "when the mirrored config includes invalid shared folders" do
|
@@ -19,10 +19,10 @@ describe Vagrant::Mirror::Rsync do
|
|
19
19
|
File.stub(:directory?).with('c:/vagrant/dir').and_return(true)
|
20
20
|
end
|
21
21
|
|
22
|
-
subject { Vagrant::Mirror::Rsync.new(vm, guest_sf_path, host_path, mirror_config) }
|
23
|
-
|
24
22
|
describe "#run" do
|
25
23
|
|
24
|
+
subject { Vagrant::Mirror::Rsync.new(vm, guest_sf_path, host_path, mirror_config) }
|
25
|
+
|
26
26
|
shared_examples "running rsync to update the path" do | path, expect_source, expect_dest |
|
27
27
|
context "with no exclude paths" do
|
28
28
|
it "runs the expected rsync command" do
|
@@ -34,10 +34,10 @@ describe Vagrant::Mirror::Rsync do
|
|
34
34
|
|
35
35
|
context "with exclude paths" do
|
36
36
|
let (:mirror_config) { { :name => 'v-root', :guest_path => '/var/vagrant', :delete => false,
|
37
|
-
:exclude => ['
|
37
|
+
:exclude => ['/.git', 'cache'], :beep => false, :symlinks => [] } }
|
38
38
|
|
39
39
|
it "runs the expected rsync command" do
|
40
|
-
channel.should_receive(:sudo).with("rsync -av --exclude '
|
40
|
+
channel.should_receive(:sudo).with("rsync -av --exclude '/.git' --exclude 'cache' #{expect_source} #{expect_dest}")
|
41
41
|
|
42
42
|
subject.run(path)
|
43
43
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-mirror
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1.alpha
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-02 00:00:00.
|
12
|
+
date: 2013-04-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: vagrant
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: 1.0.5
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.0.5
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: listen
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '0'
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: rake
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,10 +53,15 @@ dependencies:
|
|
43
53
|
version: '0'
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: rspec
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ! '>='
|
@@ -54,10 +69,15 @@ dependencies:
|
|
54
69
|
version: '0'
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
58
78
|
- !ruby/object:Gem::Dependency
|
59
79
|
name: guard
|
60
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
82
|
requirements:
|
63
83
|
- - ! '>='
|
@@ -65,10 +85,15 @@ dependencies:
|
|
65
85
|
version: '0'
|
66
86
|
type: :development
|
67
87
|
prerelease: false
|
68
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: guard-rspec
|
71
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
72
97
|
none: false
|
73
98
|
requirements:
|
74
99
|
- - ! '>='
|
@@ -76,7 +101,12 @@ dependencies:
|
|
76
101
|
version: '0'
|
77
102
|
type: :development
|
78
103
|
prerelease: false
|
79
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
80
110
|
description: A Vagrant plugin that mirrors folders from host to guest by monitoring
|
81
111
|
filesystem
|
82
112
|
email:
|
@@ -104,9 +134,6 @@ files:
|
|
104
134
|
- lib/vagrant-mirror/middleware/mirror.rb
|
105
135
|
- lib/vagrant-mirror/middleware/sync.rb
|
106
136
|
- lib/vagrant-mirror/rsync.rb
|
107
|
-
- lib/vagrant-mirror/sync/all.rb
|
108
|
-
- lib/vagrant-mirror/sync/base.rb
|
109
|
-
- lib/vagrant-mirror/sync/changes.rb
|
110
137
|
- lib/vagrant-mirror/version.rb
|
111
138
|
- lib/vagrant_init.rb
|
112
139
|
- spec/spec_helper.rb
|
@@ -138,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
165
|
version: 1.3.1
|
139
166
|
requirements: []
|
140
167
|
rubyforge_project:
|
141
|
-
rubygems_version: 1.
|
168
|
+
rubygems_version: 1.8.24
|
142
169
|
signing_key:
|
143
170
|
specification_version: 3
|
144
171
|
summary: A Vagrant plugin that mirrors folders from host to guest by monitoring filesystem
|
@@ -1,60 +0,0 @@
|
|
1
|
-
# Compares the contents of the host and guest paths and transfers any
|
2
|
-
# missing or modified paths to the other side of the mirror. If a whole
|
3
|
-
# directory is missing, uses recursive upload/download from the SFTP class,
|
4
|
-
# otherwise it iterates over and compares the directory contents.
|
5
|
-
#
|
6
|
-
# This class does not detect deletions - if a file is missing on one side
|
7
|
-
# of the mirror it will simply be replaced.
|
8
|
-
#
|
9
|
-
# @author Andrew Coulton < andrew@ingenerator.com >
|
10
|
-
module Vagrant
|
11
|
-
module Mirror
|
12
|
-
module Sync
|
13
|
-
class All < Base
|
14
|
-
|
15
|
-
# Compares a folder between guest and host, transferring any new or
|
16
|
-
# modified files in the right direction.
|
17
|
-
#
|
18
|
-
# @param [string] The base path to compare
|
19
|
-
def execute(path)
|
20
|
-
path = path.chomp('/')
|
21
|
-
host_dir = host_path(path).chomp('/')
|
22
|
-
guest_dir = guest_path(path).chomp('/')
|
23
|
-
|
24
|
-
if !@connection.exists?(guest_dir)
|
25
|
-
# Create the guest directory
|
26
|
-
@connection.mkdir(guest_dir)
|
27
|
-
end
|
28
|
-
|
29
|
-
if !File.exists?(host_dir)
|
30
|
-
# Create the host directory
|
31
|
-
FileUtils.mkdir_p(host_dir)
|
32
|
-
end
|
33
|
-
|
34
|
-
# If the guest path already exists, have to sync manually
|
35
|
-
# First get a combined listing of the two paths
|
36
|
-
all_files = @connection.dir_entries(guest_dir) | Dir.entries(host_dir)
|
37
|
-
all_files.each do | file |
|
38
|
-
# Ignore . and ..
|
39
|
-
if (file == '.') or (file == '..')
|
40
|
-
next
|
41
|
-
end
|
42
|
-
|
43
|
-
# Get local paths
|
44
|
-
host_file = File.join(host_dir, file)
|
45
|
-
guest_file = File.join(guest_dir, file)
|
46
|
-
# Recurse for directories
|
47
|
-
if File.directory?(host_file) \
|
48
|
-
or ( !File.exists?(host_file) and @connection.directory?(guest_file))
|
49
|
-
execute("#{path}/#{file}")
|
50
|
-
else
|
51
|
-
# Transfer new/modified files between host and guest
|
52
|
-
compare_and_transfer(host_file, guest_file)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
# Base class for file sync actions, providing common required functionality
|
2
|
-
#
|
3
|
-
# @author Andrew Coulton < andrew@ingerator.com >
|
4
|
-
module Vagrant
|
5
|
-
module Mirror
|
6
|
-
module Sync
|
7
|
-
class Base
|
8
|
-
|
9
|
-
# Initialises the synchroniser
|
10
|
-
#
|
11
|
-
# @param [Vagrant::Mirror::Connection::SFTP] The sftp connection instance
|
12
|
-
# @param [String] The root path on the host to mirror
|
13
|
-
# @param [String] The root path on the guest to mirror
|
14
|
-
# @param [Vagrant::UI::Interface] The Vagrant UI class
|
15
|
-
def initialize(connection, host_path, guest_path, ui)
|
16
|
-
@connection = connection
|
17
|
-
@host_root = host_path
|
18
|
-
@guest_root = guest_path
|
19
|
-
@ui = ui
|
20
|
-
end
|
21
|
-
|
22
|
-
# ==================================================================
|
23
|
-
# Begin protected internal methods
|
24
|
-
# ==================================================================
|
25
|
-
protected
|
26
|
-
|
27
|
-
# Gets the absolute host path for a file
|
28
|
-
#
|
29
|
-
# @param [String] Relative path to the file
|
30
|
-
# @return [String] Absolute path to the file on the host
|
31
|
-
def host_path(relative_path)
|
32
|
-
File.join(@host_root, relative_path)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Gets the absolute guest path for a file
|
36
|
-
#
|
37
|
-
# @param [String] Relative path to the file
|
38
|
-
# @return [String] Absolute path to the file on the guest
|
39
|
-
def guest_path(relative_path)
|
40
|
-
File.join(@guest_root, relative_path)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Gets the mtime of a file on the host from an absolute path
|
44
|
-
#
|
45
|
-
# @param [String] Absolute host path
|
46
|
-
# @return [Time] mtime, or nil if the file does not exist
|
47
|
-
def host_mtime(path)
|
48
|
-
if !File.exists?(path)
|
49
|
-
return nil
|
50
|
-
end
|
51
|
-
return File.mtime(path)
|
52
|
-
end
|
53
|
-
|
54
|
-
# Gets the mtime of a file on the guest from an absolute path
|
55
|
-
#
|
56
|
-
# @param [String] Absolute guest path
|
57
|
-
# @return [Time] mtime, or nil if the file does not exist
|
58
|
-
def guest_mtime(path)
|
59
|
-
@connection.mtime(path)
|
60
|
-
end
|
61
|
-
|
62
|
-
# Compares files on the host and the guest and transfers the newest
|
63
|
-
# to the other side.
|
64
|
-
#
|
65
|
-
# @param [String] Absolute host path
|
66
|
-
# @param [String] Absolute guest path
|
67
|
-
def compare_and_transfer(host_file, guest_file)
|
68
|
-
|
69
|
-
# Get the mtimes
|
70
|
-
host_time = host_mtime(host_file)
|
71
|
-
guest_time = guest_mtime(guest_file)
|
72
|
-
|
73
|
-
# Check what to do
|
74
|
-
if (host_time.nil? and guest_time.nil?) then
|
75
|
-
# Report an error
|
76
|
-
@ui.error("#{host_file} was not found on either the host or guest filesystem - cannot sync")
|
77
|
-
elsif (host_time == guest_time)
|
78
|
-
# Do nothing
|
79
|
-
return
|
80
|
-
elsif (guest_time.nil?)
|
81
|
-
# Transfer to guest
|
82
|
-
@connection.upload(host_file, guest_file, host_time)
|
83
|
-
elsif (host_time.nil?)
|
84
|
-
# Transfer to host
|
85
|
-
@connection.download(guest_file, host_file, guest_time)
|
86
|
-
elsif (host_time > guest_time)
|
87
|
-
# Transfer to guest
|
88
|
-
@connection.upload(host_file, guest_file, host_time)
|
89
|
-
elsif (host_time < guest_time)
|
90
|
-
# Transfer to guest
|
91
|
-
@connection.download(guest_file, host_file, guest_time)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
# Processes notified file additions, modifications and deletions notified by
|
2
|
-
# guard/listen, and replays them on the other side of the mirror.
|
3
|
-
# The execute method will be called for each changeset notified whether
|
4
|
-
# by guard or over the TCP socket (from guard on the guest). This could
|
5
|
-
# cause a race condition as changes on the guest trigger changes on the host
|
6
|
-
# and vice versa.
|
7
|
-
#
|
8
|
-
# Therefore, on notification of added or modified file, the class just
|
9
|
-
# syncs whichever is the newest file between the two machines. On deletion
|
10
|
-
# it will quietly fail if the file it is notified of has already been
|
11
|
-
# deleted.
|
12
|
-
#
|
13
|
-
# @author Andrew Coulton < andrew@ingenerator.com >
|
14
|
-
module Vagrant
|
15
|
-
module Mirror
|
16
|
-
module Sync
|
17
|
-
class Changes < Base
|
18
|
-
|
19
|
-
# Compares a single notified changeset and transfers any changed,
|
20
|
-
# modified or removed files in the right direction.
|
21
|
-
#
|
22
|
-
# @param [Symbol] Which side of the mirror the change was detected
|
23
|
-
# @param [Array] Array of added paths
|
24
|
-
# @param [Array] Array of changed paths
|
25
|
-
# @param [Array] Array of removed paths
|
26
|
-
def execute(source, added, modified, removed)
|
27
|
-
|
28
|
-
# Combine added and modified, they're the same for our purposes
|
29
|
-
changed = added + modified
|
30
|
-
changed.each do |file|
|
31
|
-
# Transfer the newest file to the other side, or do nothing
|
32
|
-
compare_and_transfer(host_path(file), guest_path(file))
|
33
|
-
end
|
34
|
-
|
35
|
-
# Process deleted files
|
36
|
-
removed.each do |file|
|
37
|
-
# Expect a cascade - only delete on opposite side if exists
|
38
|
-
if source == :host
|
39
|
-
guest_file = guest_path(file)
|
40
|
-
if !guest_mtime(guest_file).nil?
|
41
|
-
@connection.delete(guest_file)
|
42
|
-
else
|
43
|
-
@ui.info("#{file} was not found on guest - nothing to delete")
|
44
|
-
end
|
45
|
-
elsif source == :guest
|
46
|
-
host_file = host_path(file)
|
47
|
-
if File.exists?(host_file)
|
48
|
-
File.delete(host_file)
|
49
|
-
else
|
50
|
-
@ui.info("#{file} was not found on host - nothing to delete")
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Complete all transfers
|
56
|
-
@connection.finish_transfers
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|