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