Repository: smerrill/vagrant-gatling-rsync Branch: master Commit: 038ca4c3ba4b Files: 21 Total size: 25.7 KB Directory structure: gitextract_7sn9rhpq/ ├── .gitignore ├── .ruby-version ├── CHANGELOG.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── example/ │ ├── docker/ │ │ └── Dockerfile │ └── vagrant/ │ └── Vagrantfile ├── lib/ │ ├── vagrant-gatling-rsync/ │ │ ├── action/ │ │ │ └── startup_rsync.rb │ │ ├── command/ │ │ │ └── rsync_auto.rb │ │ ├── config.rb │ │ ├── errors.rb │ │ ├── listen/ │ │ │ ├── listenlinux.rb │ │ │ ├── listenosx.rb │ │ │ └── listenwindows.rb │ │ ├── plugin.rb │ │ └── version.rb │ └── vagrant-gatling-rsync.rb ├── locales/ │ └── en.yml └── vagrant-gatling-rsync.gemspec ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp *.swp *.swo example/files/* example/vagrant/.vagrant ================================================ FILE: .ruby-version ================================================ 2.6.2 ================================================ FILE: CHANGELOG.md ================================================ ## 1.0 (June 02, 2020) This release adds compatibility with Vagrant 2.2.5+. Small parts of the example Vagrantfile and the Gemfile and Gemspec have also been cleaned up. FEATURES: - Add compatibility with Vagrant 2.2.5+. Thanks to @leejo for the PR. [GH-37] ## 0.9.0 (June 28, 2015) This release adds two big features: Windows support and automatic sync on startup. It also adds the `config.gatling.rsync_on_startup` configuration option to turn automatic rsync on startup off if you do not want it. It also updates the Gemfile to use Vagrant 1.7.2 for development. The gem should still work with Vagrant 1.5.1+. FEATURES: - Add support for Windows. Thanks to @mfradcourt for wiring it up. [GH-21] - Add automatic sync startup on `vagrant up` or `vagrant reload` if rsync folders are present. [GH-14] ## 0.1.0 (January 04, 2015) This release adds feature parity with Vagrant core rsync-auto by doing a sync when gatling-rsync is started. FEATURES: - Perform an initial rsync when the watcher starts. [GH-13] ## 0.0.4 (August 24, 2014) This release adds notification of time and duration of rsyncs. It also adds the `config.gatling.time_format` configuration option to allow customization of the time format string when time information is printed to the console. It also updates the Gemfile to use Vagrant 1.6.4 so that I can test on Linux using the Docker provider. This should not have any impact on using the gem with 1.5.1+ versions of Vagrant, however. FEATURES: - Add output to note when an rsync finishes and how long it took. [GH-7, GH-10] BUG FIXES: - The plugin now correctly outputs an error instead of failing to load on Vagrant versions < 1.5.1. [GH-11] ## 0.0.3 (May 02, 2014) Bugfix release. BUG FIXES: - Fix the plugin under multi-box environments. Thanks to @mattchannelgrabber. [GH-5] ## 0.0.2 (April 27, 2014) Bugfix release. BUG FIXES: - Catch ThreadErrors (this sometimes happens in practice on OS X.) - Reflect that this plugin requires Vagrant 1.5.1+. ## 0.0.1 (March 23, 2014) Initial release. FEATURES: - Implement an rb-fsevent adapter for Mac. - Implement an rb-inotify adapter for Linux. - Add the `vagrant gatling-rsync-auto` command. - Implement the first draft of a config option to allow changing the latency. ## Backlog - Test and release the Windows adapter. - Allow configuring and running the rsync daemon to avoid SSH overhead. - Get latency validation working. ================================================ FILE: Gemfile ================================================ source 'https://rubygems.org' # Specify your gem's dependencies in vagrant-gatling-rsync.gemspec gemspec group :development do gem "vagrant", :git => "https://github.com/mitchellh/vagrant.git", :tag => 'v2.2.16' end group :plugins do gemspec end ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2014 Steven Merrill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # vagrant-gatling-rsync An rsync watcher for Vagrant 1.5.1+ that uses fewer host resources at the potential cost of more rsync actions. ## Getting started To get started, you need to have Vagrant 1.5.1 installed on your Linux, Mac, or Windows host machine. To install the plugin, use the following command. ```bash vagrant plugin install vagrant-gatling-rsync ``` ## Working with this plugin Add the following information to the Vagrantfile to set the coalescing threshold in seconds. If you do not set it, it will default to 1.5. You may also specify what [Time.strftime](http://www.ruby-doc.org/core-2.0.0/Time.html#method-i-strftime) options the plugin will use when it reports on completed rsyncs. The default is "%I:%M:%S %p". You will also need to have at least one synced folder set to type "rsync" to use the plugin. ```ruby VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "hashicorp/precise64" config.vm.synced_folder "../files", "/opt/vagrant/rsynced_folder", type: "rsync", rsync__exclude: [".git/", ".idea/"] # Configure the window for gatling to coalesce writes. if Vagrant.has_plugin?("vagrant-gatling-rsync") config.gatling.latency = 2.5 config.gatling.time_format = "%H:%M:%S" end # Automatically sync when machines with rsync folders come up. config.gatling.rsync_on_startup = true end ``` With the Vagrantfile configured in this fashion, you can run the following command to sync files. ```bash vagrant gatling-rsync-auto ``` As of version 0.9.0, vagrant-gatling-rsync will automatically start the sync engine on `vagrant up` or `vagrant reload` when the machines that you bring up have one or more rsync folders defined. You can disable this behavior by setting `config.gatling.rsync_on_startup` to false. ## Why "gatling"? The gatling gun was the first gun capable of firing continuously. ## This plugin The built-in rsync-auto plugin sometimes uses a lot of CPU and disk I/O when it starts up on very large rsynced directories. This plugin is designed to work well with such large rsynced folders. The rsync-auto command that ships with Vagrant 1.5 uses the listen gem. The Listen gem is quite thorough - it uses Celluloid to spin up an actor system and it checks file contents on OS X to ensure that running "touch" on a file (to do a write but not update its content) will not fire the rsync command. The downside of using Listen is that it takes a large amount of host resources to monitor large directory structures. This gem works well with to monitor directories hierarchies with 10,000-100,000 files. This gem's implementation is much closer to the underlying fsevent or inotify APIs, which allows for higher performance. ## Event coalescing This plugin also coalesces events for you. The default latency is 1.5 seconds. It is configurable through the `config.gatling.latency` parameter. If you specify a latency of two seconds, this plugin will not fire a `vagrant rsync` until two contiguous seconds without file events have passed. This will delay rsyncs from happening if many writes are happening on the host (during a `make` or a `git clone`, for example) until the activity has leveled off. ## Authors Steven Merrill (@stevenmerrill) originally had the idea to tap into rb-fsevent and rb-inotify to more efficiently rsync files. Doug Marcey (@dougmarcey) provided considerable guidance in the implementation of the coalescing functionality and wrote the initial sketch of the Linux and Windows adapters. ================================================ FILE: Rakefile ================================================ require "bundler/gem_tasks" ================================================ FILE: example/docker/Dockerfile ================================================ # Baseimage for Docker-related Vagrant environments FROM ubuntu:20.04 MAINTAINER Sergey Arkhipov # Environment variables ENV DEBIAN_FRONTEND noninteractive ENV TERM linux ## Do common baseimage actions #RUN echo "/root" > /etc/container_environment/HOME && \ #echo "noninteractive" > /etc/container_environment/DEBIAN_FRONTEND && \ #echo "linux" > /etc/container_environment/TERM && \ #rm -f /etc/service/sshd/down && \ #/usr/sbin/enable_insecure_key && \ #/etc/my_init.d/00_regen_ssh_host_keys.sh # Install necessary packages RUN apt-get -qq update && \ apt-get -qq install -y --no-install-recommends \ git \ vim \ nano \ curl \ openssh-server \ ca-certificates \ sudo \ rsync && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* # Add Vagrant user and key, prep sshd to run RUN useradd vagrant -m && \ mkdir -p /home/vagrant/.ssh && \ curl -sL https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub > /home/vagrant/.ssh/authorized_keys && \ chown -R vagrant: /home/vagrant && \ echo 'vagrant ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \ mkdir -p /run/sshd # Cleanups RUN rm -rf /tmp/* /var/tmp/* /etc/fstab # Init process is entrypoint CMD ["/usr/sbin/sshd", "-D"] ================================================ FILE: example/vagrant/Vagrantfile ================================================ # -*- mode: ruby -*- # vi: set ft=ruby : # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "centos/7" config.vm.provider "docker" do |d, override| d.image = "smerrill/vagrant-ubuntu-focal" d.has_ssh = true # This is needed if you have non-Docker provisioners in the Vagrantfile. override.vm.box = nil end config.vm.provider "lxc" do |d, override| override.vm.box = "smerrill/centos-7" end # When using gatling rsync in your projects, you should wrap these configs in # an 'if Vagrant.has_plugin?("vagrant-gatling-rsync")' test. # Configure the window for gatling to coalesce writes. config.gatling.latency = 0.4 config.gatling.time_format = "%H:%M:%S" # Gatling rsync will run `vagrant gatling-rsync-auto` after the machines in # your Vagrant environment start unles you set this to false. config.gatling.rsync_on_startup = true config.vm.synced_folder ".", "/vagrant", disabled: true # Add a multi-box setup. config.vm.define "rsync", primary: true do |m| m.vm.synced_folder "../files", "/opt/vagrant/rsynced_folder", type: "rsync", rsync__exclude: [".git/", ".idea/"] end config.vm.define "rsync2", primary: true do |m| m.vm.synced_folder "../files", "/opt/vagrant/rsynced_folder", type: "rsync", rsync__exclude: [".git/", ".idea/"] end config.vm.define "norsync" do |m| end end ================================================ FILE: lib/vagrant-gatling-rsync/action/startup_rsync.rb ================================================ require "vagrant" module VagrantPlugins module GatlingRsync class StartupRsync include Vagrant::Action::Builtin::MixinSyncedFolders def initialize(app, env) @app = app @gatling_startup_registered = false @rsync_folder_count = 0 end def call(env) folders = synced_folders(env[:machine]) @rsync_folder_count += folders[:rsync].size if folders.key?(:rsync) @app.call(env) # Ensure only one at_exit block is registered. return unless @gatling_startup_registered == false return unless env[:machine].config.gatling.rsync_on_startup == true at_exit do unless $!.is_a?(SystemExit) env[:ui].warn "Vagrant's startup was interrupted by an exception." exit 1 end exit_status = $!.status if exit_status != 0 env[:ui].warn "The previous process exited with exit code #{exit_status}." exit exit_status end # Don't run if there are no rsynced folders. unless @rsync_folder_count == 0 then env[:ui].info I18n.t("vagrant_gatling_rsync.startup_sync") env[:machine].env.cli("gatling-rsync-auto") end end @gatling_startup_registered = true end end end end ================================================ FILE: lib/vagrant-gatling-rsync/command/rsync_auto.rb ================================================ require "log4r" require "optparse" require "vagrant" module VagrantPlugins module GatlingRsync class GatlingRsyncAuto < Vagrant.plugin(2, :command) # This is a sanity check to make sure no one is attempting to install # this into an early Vagrant version. if Gem::Version.new(Vagrant::VERSION) < Gem::Version.new("1.5.1") raise Errors::Vagrant15RequiredError end include Vagrant::Action::Builtin::MixinSyncedFolders def self.synopsis "syncs rsync synced folders when folders change" end def execute @logger = Log4r::Logger.new("vagrant::commands::gatling-rsync-auto") opts = OptionParser.new do |o| o.banner = "Usage: vagrant gatling-rsync-auto [vm-name]" o.separator "" end # Parse the options and return if we don't have any target. argv = parse_options(opts) return if !argv latency = nil # Build up the paths that we need to listen to. paths = {} ignores = [] with_target_vms(argv) do |machine| latency = machine.config.gatling.latency folders = synced_folders(machine)[:rsync] next if !folders || folders.empty? # Get the SSH info for this machine so we can do an initial # sync to the VM, just as core `vagrant rsync-auto` does. ssh_info = machine.ssh_info if ssh_info machine.ui.info(I18n.t("vagrant.rsync_auto_initial")) folders.each do |id, folder_opts| VagrantPlugins::SyncedFolderRSync::RsyncHelper.rsync_single(machine, ssh_info, folder_opts) end end folders.each do |id, folder_opts| # If we marked this folder to not auto sync, then # don't do it. next if folder_opts.has_key?(:auto) && !folder_opts[:auto] hostpath = folder_opts[:hostpath] hostpath = File.expand_path(hostpath, machine.env.root_path) paths[hostpath] ||= [] paths[hostpath] << { id: id, machine: machine, opts: folder_opts, } if folder_opts[:exclude] Array(folder_opts[:exclude]).each do |pattern| if Gem::Version.new(Vagrant::VERSION) < Gem::Version.new("2.2.5") ignores << VagrantPlugins::SyncedFolderRSync::RsyncHelper.exclude_to_regexp(hostpath, pattern.to_s) else ignores << VagrantPlugins::SyncedFolderRSync::RsyncHelper.exclude_to_regexp(pattern.to_s) end end end end end # Output to the user what paths we'll be watching paths.keys.sort.each do |path| paths[path].each do |path_opts| path_opts[:machine].ui.info(I18n.t( "vagrant.rsync_auto_path", path: path.to_s, )) end end @logger.info("Listening to paths: #{paths.keys.sort.inspect}") @logger.info("Ignoring #{ignores.length} paths:") ignores.each do |ignore| @logger.info(" -- #{ignore.to_s}") end case RUBY_PLATFORM when /darwin/ ListenOSX.new(paths, ignores, latency, @logger, self.method(:callback)).run when /linux/ ListenLinux.new(paths, ignores, latency, @logger, self.method(:callback)).run when /cygwin|mswin|mingw|bccwin|wince|emx/ ListenWindows.new(paths, ignores, latency, @logger, self.method(:callback)).run else # @TODO: Raise this earlier? raise Errors::OSNotSupportedError end 0 end # This callback gets called when any directory changes. def callback(paths, ignores, modified) @logger.info("File change callback called!") @logger.info(" - Paths: #{paths.inspect}") @logger.info(" - Ignores: #{ignores.inspect}") @logger.info(" - Modified: #{modified.inspect}") tosync = [] paths.each do |hostpath, folders| # Find out if this path should be synced found = catch(:done) do modified.each do |changed| match = nil ignores.each do |ignore| next unless match.nil? match = ignore.match(changed) end next unless match.nil? throw :done, true if changed.start_with?(hostpath) end # Make sure to return false if all else fails so that we # don't sync to this machine. false end # If it should be synced, store it for later tosync << folders if found end # Sync all the folders that need to be synced tosync.each do |folders| folders.each do |opts| ssh_info = opts[:machine].ssh_info do_rsync(opts[:machine], ssh_info, opts[:opts]) if ssh_info end end end def do_rsync(machine, ssh_info, opts) start_time = Time.new VagrantPlugins::SyncedFolderRSync::RsyncHelper.rsync_single(machine, ssh_info, opts) end_time = Time.new machine.ui.info(I18n.t( "vagrant_gatling_rsync.gatling_ran", date: end_time.strftime(machine.config.gatling.time_format), milliseconds: (end_time - start_time) * 1000)) end end end end ================================================ FILE: lib/vagrant-gatling-rsync/config.rb ================================================ require "vagrant" module VagrantPlugins module GatlingRsync class Config < Vagrant.plugin(2, :config) attr_accessor :latency attr_accessor :time_format attr_accessor :rsync_on_startup def initialize @latency = UNSET_VALUE @time_format = UNSET_VALUE @rsync_on_startup = UNSET_VALUE end def finalize! @latency = 1.5 if @latency == UNSET_VALUE @time_format = "%I:%M:%S %p" if @time_format == UNSET_VALUE if @rsync_on_startup == UNSET_VALUE @rsync_on_startup = true else @rsync_on_startup = !!@rsync_on_startup end end # @TODO: This does not appear to be called. def validate(machine) errors = _detected_errors if @latency == UNSET_VALUE return elsif not @latency.is_a? Numeric @latency = 1.5 # @TODO: Translate. errors << "The latency must be set to a number. Substituting 1.5 as a value." elsif @latency < 0.2 @latency = 0.2 # @TODO: Translate. errors << "The latency may not be below 0.2 seconds." end { "gatling" => errors } end end end end ================================================ FILE: lib/vagrant-gatling-rsync/errors.rb ================================================ require "vagrant" module VagrantPlugins module GatlingRsync module Errors class VagrantGatlingRsyncError < Vagrant::Errors::VagrantError error_namespace("vagrant_gatling_rsync.errors") end class OSNotSupportedError < VagrantGatlingRsyncError error_key(:os_not_supported) end class Vagrant15RequiredError < VagrantGatlingRsyncError error_key(:vagrant_15_required) end end end end ================================================ FILE: lib/vagrant-gatling-rsync/listen/listenlinux.rb ================================================ require "rb-inotify" module VagrantPlugins module GatlingRsync class ListenLinux def initialize(paths, ignores, latency, logger, callback) @paths = paths @ignores = ignores @latency = latency @logger = logger @callback = callback end def run @logger.info("Listening via: rb-inotify on Linux.") notifier = INotify::Notifier.new @paths.keys.each do |path| notifier.watch(path, :modify, :create, :delete, :recursive) {} end loop do directories = Set.new begin loop do events = [] events = Timeout::timeout(@latency) { notifier.read_events } events.each { |e| directories << e.absolute_name } end rescue Timeout::Error @logger.info("Breaking out of the loop at #{Time.now.to_s}.") end @logger.info("Detected changes to #{directories.inspect}.") unless directories.empty? @callback.call(@paths, @ignores, directories) unless directories.empty? end end end end end ================================================ FILE: lib/vagrant-gatling-rsync/listen/listenosx.rb ================================================ require "rb-fsevent" module VagrantPlugins module GatlingRsync class ListenOSX def initialize(paths, ignores, latency, logger, callback) @paths = paths @ignores = ignores @latency = latency @options = { # We set this to a small value to ensure that we can coalesce the # events together to prevent rsyncing too often under heavy write # load. :latency => 0.1, :no_defer => false, } @logger = logger @callback = callback end def run @logger.info("Listening via: rb-fsevent on Mac OS X.") changes = Queue.new fsevent = FSEvent.new fsevent.watch @paths.keys, @options do |directories| directories.each { |d| changes << d } end Thread.new { fsevent.run } loop do directories = Set.new begin loop do @logger.info("Starting the timeout at #{Time.now.to_s}.") change = Timeout::timeout(@latency) { changes.pop } directories << change unless change.nil? end rescue Timeout::Error, ThreadError @logger.info("Breaking out of the loop at #{Time.now.to_s}.") end @logger.info("Detected changes to #{directories.inspect}.") unless directories.empty? @callback.call(@paths, @ignores, directories) unless directories.empty? end end end end end ================================================ FILE: lib/vagrant-gatling-rsync/listen/listenwindows.rb ================================================ # @TODO: Note that this is entirely untested and not yet implemented. require "wdm" module VagrantPlugins module GatlingRsync class ListenWindows def initialize(paths, ignores, latency, logger, callback) @paths = paths @ignores = ignores @latency = latency @logger = logger @callback = callback end def run @logger.info("Listening via: WDM on Windows.") monitor = WDM::Monitor.new changes = Queue.new @paths.keys.each do |path| monitor.watch_recursively(path.dup) { |change| changes << change } end Thread.new { monitor.run! } loop do directories = Set.new begin loop do change = Timeout::timeout(@latency) { changes.pop } directories << change.path end rescue Timeout::Error @logger.info("Breaking out of the loop at #{Time.now.to_s}.") end @logger.info(directories.inspect) unless directories.empty? @callback.call(@paths, @ignores, directories) unless directories.empty? end end end end end ================================================ FILE: lib/vagrant-gatling-rsync/plugin.rb ================================================ begin require "vagrant" rescue LoadError raise "The Vagrant gatling rsync plugin must be run within Vagrant." end module VagrantPlugins module GatlingRsync class Plugin < Vagrant.plugin(2) name "Gatling Rsync" description <<-DESC Rsync large project directories to your Vagrant VM without using many resources on the host. DESC # This initializes the internationalization strings. def self.setup_i18n I18n.load_path << File.expand_path("locales/en.yml", GatlingRsync.source_root) I18n.reload! end action_hook "startup-rsync" do |hook| setup_i18n require_relative "action/startup_rsync" hook.after Vagrant::Action::Builtin::SyncedFolders, StartupRsync end command "gatling-rsync-auto" do setup_i18n require_relative "command/rsync_auto" GatlingRsyncAuto end config "gatling" do require_relative "config" Config end end end end ================================================ FILE: lib/vagrant-gatling-rsync/version.rb ================================================ module VagrantPlugins module GatlingRsync VERSION = "1.0.1" end end ================================================ FILE: lib/vagrant-gatling-rsync.rb ================================================ # This file is required because Vagrant's plugin system expects # an eponymous ruby file matching the rubygem. # # So this gem is called 'vagrant-gatling-rsync' and thus vagrant tries # to require "vagrant-gatling-rsync" require "vagrant-gatling-rsync/plugin" require "pathname" module VagrantPlugins module GatlingRsync lib_path = Pathname.new(File.expand_path("../vagrant-gatling-rsync", __FILE__)) autoload :Errors, lib_path.join("errors") autoload :ListenOSX, lib_path.join("listen/listenosx") autoload :ListenLinux, lib_path.join("listen/listenlinux") autoload :ListenWindows, lib_path.join("listen/listenwindows") # This returns the path to the source of this plugin. # # @return [Pathname] def self.source_root @source_root ||= Pathname.new(File.expand_path("../../", __FILE__)) end end end ================================================ FILE: locales/en.yml ================================================ en: vagrant_gatling_rsync: gatling_ran: |- %{date}: The rsync operation completed in %{milliseconds} milliseconds. startup_sync: |- vagrant-gatling-rsync is starting the sync engine because you have at least one rsync folder. To disable this behavior, set `config.gatling.rsync_on_startup = false` in your Vagrantfile. errors: os_not_supported: |- The vagrant-gatling-rsync plugin does not support your OS. vagrant_15_required: |- The vagrant-gatling-rsync plugin requires Vagrant 1.5.1 or newer to function. ================================================ FILE: vagrant-gatling-rsync.gemspec ================================================ # coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'vagrant-gatling-rsync/version' Gem::Specification.new do |spec| spec.name = "vagrant-gatling-rsync" spec.version = VagrantPlugins::GatlingRsync::VERSION spec.authors = ["Steven Merrill"] spec.email = ["steven.merrill@gmail.com"] spec.summary = %q{A lighter-weight Vagrant plugin for watching and rsyncing directories.} spec.description = %q{The gatling-rsync plugin runs on Mac and Linux and is far less CPU-intensive than the built-in rsync-auto.} spec.homepage = "" spec.license = "MIT" spec.files = `git ls-files -z`.split("\x0").reject {|f| f.start_with?('example/files')} spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_development_dependency "rake" spec.add_development_dependency "pry" end