vagrant-mirror 0.1.0.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/.gitignore +17 -0
- data/.rspec +3 -0
- data/.travis.yml +3 -0
- data/CONTRIBUTING.md +43 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +85 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +20 -0
- data/README.md +153 -0
- data/Rakefile +29 -0
- data/lib/vagrant-mirror/command.rb +71 -0
- data/lib/vagrant-mirror/config.rb +73 -0
- data/lib/vagrant-mirror/errors.rb +42 -0
- data/lib/vagrant-mirror/listener/host.rb +42 -0
- data/lib/vagrant-mirror/middleware/base.rb +65 -0
- data/lib/vagrant-mirror/middleware/mirror.rb +108 -0
- data/lib/vagrant-mirror/middleware/sync.rb +92 -0
- data/lib/vagrant-mirror/rsync.rb +91 -0
- data/lib/vagrant-mirror/sync/all.rb +60 -0
- data/lib/vagrant-mirror/sync/base.rb +98 -0
- data/lib/vagrant-mirror/sync/changes.rb +61 -0
- data/lib/vagrant-mirror/version.rb +5 -0
- data/lib/vagrant-mirror.rb +34 -0
- data/lib/vagrant_init.rb +4 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/vagrant-mirror/command_spec.rb +91 -0
- data/spec/vagrant-mirror/config_spec.rb +161 -0
- data/spec/vagrant-mirror/listener/host_spec.rb +96 -0
- data/spec/vagrant-mirror/middleware/mirror_spec.rb +188 -0
- data/spec/vagrant-mirror/middleware/sync_spec.rb +152 -0
- data/spec/vagrant-mirror/rsync_spec.rb +75 -0
- data/spec/vagrant-mirror_spec.rb +5 -0
- data/vagrant-mirror.gemspec +27 -0
- metadata +153 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
We love pull requests. Here's a quick guide:
|
2
|
+
|
3
|
+
1. Fork the repo, and make your changes.
|
4
|
+
|
5
|
+
2. Once you're ready to submit, rebase your branch against our master branch to
|
6
|
+
maintain a clean history and ensure you're up to date with all the most recent
|
7
|
+
changes.
|
8
|
+
|
9
|
+
3. Run the tests. We only take pull requests with passing tests, and it's great
|
10
|
+
to know that you have a clean slate: `bundle && rake`
|
11
|
+
|
12
|
+
4. Add a test for your change. Only refactoring and documentation changes
|
13
|
+
require no new tests. If you are adding functionality or fixing a bug, we need
|
14
|
+
a test!
|
15
|
+
|
16
|
+
5. Make the test pass.
|
17
|
+
|
18
|
+
6. Push to your fork and submit a pull request.
|
19
|
+
|
20
|
+
|
21
|
+
At this point you're waiting on us. We like to at least comment on, if not
|
22
|
+
accept, pull requests within three business days (and, typically, one business
|
23
|
+
day). We may suggest some changes or improvements or alternatives. Your pull request
|
24
|
+
will be built by [Travis](https://travis-ci.org/ingenerator/vagrant-mirror) first -
|
25
|
+
if the build fails please fix that first.
|
26
|
+
|
27
|
+
Some things that will increase the chance that your pull request is accepted,
|
28
|
+
taken straight from the Ruby on Rails guide:
|
29
|
+
|
30
|
+
* Include tests that fail without your code, and pass with it
|
31
|
+
* Update the documentation, the surrounding one, examples elsewhere, guides,
|
32
|
+
whatever is affected by your contribution
|
33
|
+
|
34
|
+
Syntax:
|
35
|
+
|
36
|
+
* Two spaces, no tabs.
|
37
|
+
* No trailing whitespace. Blank lines should not have any space.
|
38
|
+
* Prefer &&/|| over and/or.
|
39
|
+
* MyClass.my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
|
40
|
+
* a = b and not a=b.
|
41
|
+
* Follow the conventions you see used in the source already.
|
42
|
+
|
43
|
+
And in case we didn't emphasize it enough: we love tests!
|
data/Gemfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Dependencies specified in the gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem 'rb-inotify', :require => false
|
8
|
+
gem 'rb-fsevent', :require => false
|
9
|
+
gem 'rb-fchange', :require => false
|
10
|
+
gem 'wdm', :require => false, :platforms => [:mswin, :mingw]
|
11
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
vagrant-mirror (0.0.1)
|
5
|
+
listen
|
6
|
+
vagrant (~> 1.0.5)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
archive-tar-minitar (0.5.2)
|
12
|
+
childprocess (0.3.9)
|
13
|
+
ffi (~> 1.0, >= 1.0.11)
|
14
|
+
coderay (1.0.8)
|
15
|
+
diff-lcs (1.1.3)
|
16
|
+
erubis (2.7.0)
|
17
|
+
ffi (1.2.0)
|
18
|
+
ffi (1.2.0-x86-mingw32)
|
19
|
+
guard (1.6.1)
|
20
|
+
listen (>= 0.6.0)
|
21
|
+
lumberjack (>= 1.0.2)
|
22
|
+
pry (>= 0.9.10)
|
23
|
+
thor (>= 0.14.6)
|
24
|
+
guard-rspec (2.3.3)
|
25
|
+
guard (>= 1.1)
|
26
|
+
rspec (~> 2.11)
|
27
|
+
i18n (0.6.4)
|
28
|
+
json (1.7.7)
|
29
|
+
listen (0.7.0)
|
30
|
+
log4r (1.1.10)
|
31
|
+
lumberjack (1.0.2)
|
32
|
+
method_source (0.8.1)
|
33
|
+
net-scp (1.0.4)
|
34
|
+
net-ssh (>= 1.99.1)
|
35
|
+
net-ssh (2.2.2)
|
36
|
+
pry (0.9.10)
|
37
|
+
coderay (~> 1.0.5)
|
38
|
+
method_source (~> 0.8)
|
39
|
+
slop (~> 3.3.1)
|
40
|
+
pry (0.9.10-x86-mingw32)
|
41
|
+
coderay (~> 1.0.5)
|
42
|
+
method_source (~> 0.8)
|
43
|
+
slop (~> 3.3.1)
|
44
|
+
win32console (~> 1.3)
|
45
|
+
rake (10.0.3)
|
46
|
+
rb-fchange (0.0.6)
|
47
|
+
ffi
|
48
|
+
rb-fsevent (0.9.3)
|
49
|
+
rb-inotify (0.8.8)
|
50
|
+
ffi (>= 0.5.0)
|
51
|
+
rspec (2.12.0)
|
52
|
+
rspec-core (~> 2.12.0)
|
53
|
+
rspec-expectations (~> 2.12.0)
|
54
|
+
rspec-mocks (~> 2.12.0)
|
55
|
+
rspec-core (2.12.2)
|
56
|
+
rspec-expectations (2.12.1)
|
57
|
+
diff-lcs (~> 1.1.3)
|
58
|
+
rspec-mocks (2.12.1)
|
59
|
+
slop (3.3.3)
|
60
|
+
thor (0.16.0)
|
61
|
+
vagrant (1.0.7)
|
62
|
+
archive-tar-minitar (= 0.5.2)
|
63
|
+
childprocess (~> 0.3.1)
|
64
|
+
erubis (~> 2.7.0)
|
65
|
+
i18n (~> 0.6.0)
|
66
|
+
json (>= 1.5.1, < 1.8.0)
|
67
|
+
log4r (~> 1.1.9)
|
68
|
+
net-scp (~> 1.0.4)
|
69
|
+
net-ssh (~> 2.2.2)
|
70
|
+
wdm (0.1.0)
|
71
|
+
win32console (1.3.2-x86-mingw32)
|
72
|
+
|
73
|
+
PLATFORMS
|
74
|
+
x86-mingw32
|
75
|
+
|
76
|
+
DEPENDENCIES
|
77
|
+
guard
|
78
|
+
guard-rspec
|
79
|
+
rake
|
80
|
+
rb-fchange
|
81
|
+
rb-fsevent
|
82
|
+
rb-inotify
|
83
|
+
rspec
|
84
|
+
vagrant-mirror!
|
85
|
+
wdm
|
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 inGenerator Ltd, a company registered in Scotland no. SC435161
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# Vagrant::Mirror
|
2
|
+
|
3
|
+
[](https://travis-ci.org/ingenerator/vagrant-mirror)
|
4
|
+
|
5
|
+
**This plugin is for the 1.0.x series of Vagrant and has not been updated to work with 1.1 and
|
6
|
+
above. We plan to update it eventually, if you want it faster than that then contributions are
|
7
|
+
welcome!**
|
8
|
+
|
9
|
+
A vagrant plugin that mirrors a folder from host to guest, designed to get around the performance
|
10
|
+
issues of virtualbox shared folders and the headaches of NFS or Samba shares with a windows host and
|
11
|
+
linux guest. Tested with Windows XP and Vista hosts and Ubuntu 12.04 guest. However, it uses the
|
12
|
+
[listen](https://rubygems.org/gems/listen) gem from guard so it should be fully cross-platform. Your
|
13
|
+
guest will need to have rsync installed.
|
14
|
+
|
15
|
+
Vagrant-mirror runs on top of existing virtualbox shared folders, using rsync to mirror from the
|
16
|
+
shared folder to a local instance folder. This seems to be best for performance and limits the
|
17
|
+
number of dependencies.
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
The best option is to install the gem (note you will need to run `vagrant gem vagrant-mirror` if
|
22
|
+
using the bundled Vagrant package as this runs in isolation from your global ruby installation).
|
23
|
+
|
24
|
+
You also need to install the correct filesystem driver for your host operating system:
|
25
|
+
|
26
|
+
* For Windows - [WDM](https://github.com/Maher4Ever/wdm)
|
27
|
+
* For Linux - [rb-inotify](https://github.com/nex3/rb-inotify)
|
28
|
+
* For OS X - [rb-fsevent](https://github.com/thibaudgg/rb-fsevent)
|
29
|
+
|
30
|
+
Unfortunately there is currently no way to specify these as platform-specific dependencies in the
|
31
|
+
gemfile.
|
32
|
+
|
33
|
+
You can then add to your Vagrantfile like so:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'vagrant-mirror'
|
37
|
+
|
38
|
+
Vagrant::Config.run do | config |
|
39
|
+
#.....
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
Alternatively, add this repository alongside the Vagrantfile and require the library manually.
|
44
|
+
|
45
|
+
## Basic usage
|
46
|
+
|
47
|
+
Include paths to mirror in your Vagrantfile like so:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
# To mirror the vagrant root path
|
51
|
+
config.mirror.vagrant_root "/guest/path"
|
52
|
+
|
53
|
+
# To mirror any arbitrary path
|
54
|
+
config.vm.share_folder "foo", "guest/share/path", "host/path"
|
55
|
+
config.mirror.folder "foo", "/guest/mirror/path"
|
56
|
+
```
|
57
|
+
|
58
|
+
When you run `vagrant up` or `vagrant resume`, vagrant-mirror will:
|
59
|
+
|
60
|
+
* Ensure that your guest has any shared folders required for the pair
|
61
|
+
* Create any local symlinks required
|
62
|
+
* Run rsync on the guest to copy from the virtualbox shared folder to the local guest path
|
63
|
+
* Register with the local host filesystem for updates using using [listen](https://rubygems.org/gems/listen)
|
64
|
+
|
65
|
+
When changes are detected on the host, they will be notified by the listen gem. Once a change is
|
66
|
+
detected, the host will trigger the guest to run rsync on the changed path to update the locally
|
67
|
+
stored file.
|
68
|
+
|
69
|
+
If you want to force a full resync, you can run `vagrant mirror-sync`.
|
70
|
+
|
71
|
+
If for some reason the mirror crashes you can just run `vagrant-mirror monitor` on the host to bring
|
72
|
+
it back up.
|
73
|
+
|
74
|
+
## Advanced usage
|
75
|
+
|
76
|
+
### Mixing mirrored and shared files
|
77
|
+
|
78
|
+
Perhaps there are a few files or directories on the guest that you do want to appear on the host
|
79
|
+
too? Vagrant-mirror can create symbolic links for these from your mirror back to the virtualbox
|
80
|
+
shared folder. For example, perhaps you want the 'log' directory to work as though it were just on
|
81
|
+
the virtualbox shared folder?
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
# To mirror the vagrant root path - the options hash is also available when sharing any folder
|
85
|
+
config.mirror.vagrant_root "/guest/path", {
|
86
|
+
:symlinks => [ "/log"]
|
87
|
+
}
|
88
|
+
```
|
89
|
+
|
90
|
+
This will exclude the "/log" folder from rsync and symlink it directly to the shared folder.
|
91
|
+
|
92
|
+
### Excluding paths
|
93
|
+
|
94
|
+
Perhaps there are paths you don't require on your virtual machine. For example, syncing your docs
|
95
|
+
folder might waste performance. You can easily add paths that should be excluded from mirroring:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
# To mirror the vagrant root path - the options hash is also available when sharing any folder
|
99
|
+
config.mirror.vagrant_root "/guest/path", {
|
100
|
+
:exclude => [ "/docs"]
|
101
|
+
}
|
102
|
+
```
|
103
|
+
|
104
|
+
You can use any valid rsync exclude patterns for this option. All paths should be specified relative
|
105
|
+
to the directory being mirrored.
|
106
|
+
|
107
|
+
### Propogating deletes
|
108
|
+
|
109
|
+
By default, vagrant mirror transfers new files and folders but does not propogate deletes. This can
|
110
|
+
lead to unwanted behaviour, in particular if your application on the guest indexes or autoloads all
|
111
|
+
the files it finds. You can enable deletions with the following:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
# To mirror the vagrant root path - the options hash is also available when sharing any folder
|
115
|
+
config.mirror.vagrant_root "/guest/path", {
|
116
|
+
:delete => true
|
117
|
+
}
|
118
|
+
```
|
119
|
+
|
120
|
+
You should ensure that your "exclude" configuration includes all the paths that may be present on
|
121
|
+
the guest (build directories, cache, assets) as otherwise they will be deleted.
|
122
|
+
|
123
|
+
### Notifications
|
124
|
+
|
125
|
+
The time between updates is generally pretty fast, but it is nonzero. If you're working in fast
|
126
|
+
cycles it can be that you rerun a command on the guest before your updated files have been
|
127
|
+
transferred, which may be confusing. Avoid this by having vagrant-mirror issue a system beep whenever
|
128
|
+
transfers complete.
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
# To mirror the vagrant root path - the options hash is also available when sharing any folder
|
132
|
+
config.mirror.vagrant_root "/guest/path", {
|
133
|
+
:beep => true
|
134
|
+
}
|
135
|
+
```
|
136
|
+
|
137
|
+
## Contributing
|
138
|
+
|
139
|
+
1. Fork it
|
140
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
141
|
+
3. Commit your changes (`git commit -am 'Add some feature'`) with specs
|
142
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
143
|
+
5. Create new Pull Request
|
144
|
+
|
145
|
+
## Acknowledgements
|
146
|
+
|
147
|
+
The [vagrant-notify](https://github.com/fgrehm/vagrant-notify/) plugin was very useful in working
|
148
|
+
out how to structure this plugin.
|
149
|
+
|
150
|
+
## Copyright
|
151
|
+
|
152
|
+
Copyright (c) 2013 inGenerator Ltd. See LICENSE.txt for
|
153
|
+
further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
desc "Open an irb session preloaded with vagrant-mirror"
|
5
|
+
task :console do
|
6
|
+
sh "irb -rubygems -I lib -r vagrant-mirror"
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rspec/core/rake_task'
|
10
|
+
RSpec::Core::RakeTask.new do |t|
|
11
|
+
t.pattern = "spec/**/*_spec.rb"
|
12
|
+
end
|
13
|
+
|
14
|
+
# From the vagrant-notify gem
|
15
|
+
desc 'Outpus some information about Vagrant middleware stack useful for development (use ACTION=action_name to filter out actions)'
|
16
|
+
task 'vagrant-stack' do
|
17
|
+
require 'vagrant'
|
18
|
+
Vagrant.actions.to_hash.each do |action, stack|
|
19
|
+
next unless !ENV['ACTION'] || ENV['ACTION'] == action.to_s
|
20
|
+
|
21
|
+
puts action
|
22
|
+
stack.send(:stack).each do |middleware|
|
23
|
+
puts " #{middleware[0]}"
|
24
|
+
puts " -> #{middleware[1].inspect}" unless middleware[1].empty?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
task :default => :spec
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
# Command line tasks to run a full synchronisation of the mirrored folders,
|
4
|
+
# or to restart the live mirror (for example, if it fails). Folder mirroring
|
5
|
+
# will also be started with vagrant up and vagrant resume
|
6
|
+
module Vagrant
|
7
|
+
module Mirror
|
8
|
+
class Command < Vagrant::Command::Base
|
9
|
+
|
10
|
+
# Initializes the command and parses the subcommands from argv
|
11
|
+
def initialize(argv, env)
|
12
|
+
super
|
13
|
+
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Run the command - valid commands are:
|
17
|
+
# - vagrant mirror sync
|
18
|
+
# - vagrant mirror monitor
|
19
|
+
def execute
|
20
|
+
|
21
|
+
if @main_args.include?("-h") || @main_args.include?("--help")
|
22
|
+
# Print the help for all the box commands.
|
23
|
+
return help
|
24
|
+
end
|
25
|
+
|
26
|
+
# Currently we can only work with a single VM environment
|
27
|
+
raise Errors::SingleVMEnvironmentRequired if @env.multivm?
|
28
|
+
|
29
|
+
# Run the appropriate subcommand
|
30
|
+
case @sub_command
|
31
|
+
when 'sync'
|
32
|
+
return execute_sync
|
33
|
+
when 'monitor'
|
34
|
+
return execute_monitor
|
35
|
+
when nil
|
36
|
+
return execute_monitor
|
37
|
+
else
|
38
|
+
return help
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
# Execute the Sync middleware on the primary vm
|
45
|
+
def execute_sync
|
46
|
+
@env.primary_vm.run_action(Vagrant::Mirror::Middleware::Sync)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Execute the Mirror middleware on the primary vm
|
50
|
+
def execute_monitor
|
51
|
+
@env.primary_vm.run_action(Vagrant::Mirror::Middleware::Mirror)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Output help documentation
|
55
|
+
def help
|
56
|
+
opts = OptionParser.new do |opts|
|
57
|
+
opts.banner = "Usage: vagrant mirror <command> [<args>]"
|
58
|
+
opts.separator ""
|
59
|
+
opts.separator "Available subcommands:"
|
60
|
+
opts.separator " sync One-off synchronisation of all mirrored files"
|
61
|
+
opts.separator " monitor Monitor and mirror changes on host and guest"
|
62
|
+
opts.separator ""
|
63
|
+
opts.separator "For help on any individual command run `vagrant mirror COMMAND -h`"
|
64
|
+
end
|
65
|
+
|
66
|
+
@env.ui.info(opts.help, :prefix => false)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Holds configuration for the vagrant-mirror plugin
|
2
|
+
#
|
3
|
+
# @author Andrew Coulton < andrew@ingerator.com >
|
4
|
+
module Vagrant
|
5
|
+
module Mirror
|
6
|
+
class Config < Vagrant::Config::Base
|
7
|
+
|
8
|
+
# @return [Array] An array of hashes holding the details of folders to monitor
|
9
|
+
attr_reader :folders
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@folders = []
|
13
|
+
end
|
14
|
+
|
15
|
+
# Validates the provided configuration
|
16
|
+
# @param [Vagrant::Environment] Vagrant environment instance
|
17
|
+
# @param [Vagrant::Config::ErrorRecorder] Stack of errors in configuration
|
18
|
+
def validate(env, errors)
|
19
|
+
folders.each do | folder |
|
20
|
+
errors.add("vagrant-mirror cannot mirror an empty or nil host path") if (folder[:name].nil? || folder[:name].empty?)
|
21
|
+
errors.add("vagrant-mirror cannot mirror an empty or nil guest path") if (folder[:guest_path].nil? || folder[:guest_path].empty?)
|
22
|
+
valid_opts = [:name, :guest_path, :delete, :beep, :exclude, :symlinks]
|
23
|
+
folder.each do | option, value |
|
24
|
+
errors.add("vagrant-mirror does not understand the option #{option}") unless valid_opts.include?(option)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Shortcut to mirror the Vagrant root folder (where the Vagrantfile is stored) to a path on the guest
|
30
|
+
# @param [String] Path on the guest to mirror to
|
31
|
+
# @param [Hash] Command options - see README.md for details
|
32
|
+
def vagrant_root(guest_path, options = {} )
|
33
|
+
folder('v-root', guest_path, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Mirror a folder between the host and the guest
|
37
|
+
# @param [String] Name of the shared folder to mirror as passed to the vagrant shared folder config
|
38
|
+
# @param [String] Path on the guest to mirror to
|
39
|
+
# @param [Hash] Command options - see README.md for details
|
40
|
+
def folder(share_name, guest_path, options = {} )
|
41
|
+
# Add the default options
|
42
|
+
folder = {
|
43
|
+
:delete => false,
|
44
|
+
:beep => false,
|
45
|
+
:exclude => [],
|
46
|
+
:symlinks => []
|
47
|
+
}.merge(options)
|
48
|
+
|
49
|
+
# If there are any symlinks, they need to be added to the rsync excludes
|
50
|
+
folder[:symlinks].each do | link_path |
|
51
|
+
folder[:exclude] << link_path
|
52
|
+
end
|
53
|
+
|
54
|
+
# Add the names to the hash
|
55
|
+
folder[:name] = share_name
|
56
|
+
folder[:guest_path] = guest_path
|
57
|
+
|
58
|
+
# Store the folder details
|
59
|
+
@folders << folder
|
60
|
+
end
|
61
|
+
|
62
|
+
# Custom merge method since some keys here are merged differently.
|
63
|
+
# @param [Vagrant::Mirror::Config] Configuration to merge with this one
|
64
|
+
# @return [Vagrant::Mirror::Config] A new config instance with the merged configuration
|
65
|
+
def merge(other)
|
66
|
+
result = super
|
67
|
+
result.instance_variable_set(:@folders, @folders + other.folders)
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Mirror
|
3
|
+
module Errors
|
4
|
+
class SingleVMEnvironmentRequired < Vagrant::Errors::VagrantError
|
5
|
+
status_code(99)
|
6
|
+
|
7
|
+
def initialize()
|
8
|
+
message = "Vagrant-mirror currently only supports a single VM environment"
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Error < Vagrant::Errors::VagrantError
|
14
|
+
status_code(100)
|
15
|
+
|
16
|
+
def initialize(msg)
|
17
|
+
message = msg
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class MultipleFoldersNotSupported < Vagrant::Errors::VagrantError
|
23
|
+
status_code(101)
|
24
|
+
|
25
|
+
def initialize(msg)
|
26
|
+
message = msg
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class SharedFolderNotMapped < Vagrant::Errors::VagrantError
|
32
|
+
status_code(102)
|
33
|
+
|
34
|
+
def initialize(msg)
|
35
|
+
message = msg
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Uses Guard to listen for changes on the host filesystem, which it queues
|
2
|
+
# for review and transfer to the guest.
|
3
|
+
#
|
4
|
+
# @author Andrew Coulton < andrew@ingenerator.com >
|
5
|
+
|
6
|
+
require 'listen'
|
7
|
+
|
8
|
+
module Vagrant
|
9
|
+
module Mirror
|
10
|
+
module Listener
|
11
|
+
class Host
|
12
|
+
|
13
|
+
def initialize(path, queue)
|
14
|
+
@path = path
|
15
|
+
@queue = queue
|
16
|
+
end
|
17
|
+
|
18
|
+
# Makes a blocking call to Guard to listen on the configured path
|
19
|
+
def listen!
|
20
|
+
Listen.to(@path, :relative_paths => true) do | modified, added, removed |
|
21
|
+
@queue << {
|
22
|
+
:source => :host,
|
23
|
+
:added => added,
|
24
|
+
:modified => modified,
|
25
|
+
:removed => removed
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Runs listen! in a separate thread and returns the thread handle
|
31
|
+
#
|
32
|
+
# @return [Thread] The listener thread
|
33
|
+
def listen
|
34
|
+
Thread.new do
|
35
|
+
listen!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Base middleware with common functionality.
|
2
|
+
#
|
3
|
+
# @author Andrew Coulton < andrew@ingerator.com >
|
4
|
+
module Vagrant
|
5
|
+
module Mirror
|
6
|
+
module Middleware
|
7
|
+
class Base
|
8
|
+
|
9
|
+
# Creates an instance
|
10
|
+
#
|
11
|
+
# @param [Object] The next middleware in the chain
|
12
|
+
# @param [Vagrant::Action::Environment] The environment
|
13
|
+
def initialize(app, env)
|
14
|
+
@app = app
|
15
|
+
@env = env
|
16
|
+
end
|
17
|
+
|
18
|
+
# Executes the middleware and then continues to the next middleware in the
|
19
|
+
# stack
|
20
|
+
#
|
21
|
+
# @param [Vagrant::Action::Environment] The environment
|
22
|
+
def call(env)
|
23
|
+
mirrors = env[:vm].config.mirror.folders
|
24
|
+
if !mirrors.empty?
|
25
|
+
execute(mirrors, env)
|
26
|
+
else
|
27
|
+
env[:ui].info("No vagrant-mirror mirrored folders configured for this box")
|
28
|
+
end
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
# Iterates over a set of mirror configs, fetching the paths for the shared folder pair from
|
35
|
+
# on the guest and host and passing them together with the folder config to the passed block
|
36
|
+
#
|
37
|
+
# @param [Hash] The folder pair
|
38
|
+
def each_mirror(mirrors)
|
39
|
+
shared_folders = @env[:vm].config.vm.shared_folders
|
40
|
+
|
41
|
+
if (mirrors.count > 1)
|
42
|
+
raise Vagrant::Mirror::Errors::MultipleFoldersNotSupported.new("Sorry, vagrant-mirror doesn't support multiple base folders yet")
|
43
|
+
end
|
44
|
+
|
45
|
+
mirrors.each do | folder |
|
46
|
+
# Locate the shared folder pairing in the config
|
47
|
+
shared_folder = shared_folders[folder[:name]]
|
48
|
+
|
49
|
+
if shared_folder.nil?
|
50
|
+
raise Vagrant::Mirror::Errors::SharedFolderNotMapped.new("The folder #{folder[:name]} was not a valid Vagrant shared folder name")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Pull out the guest and host path
|
54
|
+
guest_path = shared_folder[:guestpath]
|
55
|
+
host_path = File.expand_path(shared_folder[:hostpath], @env[:root_path])
|
56
|
+
|
57
|
+
# Yield for the parent
|
58
|
+
yield host_path, guest_path, folder
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|