diff --git a/lib/vagrant/action/builtin/mixin_synced_folders.rb b/lib/vagrant/action/builtin/mixin_synced_folders.rb index d2dc76730..0f3889a0d 100644 --- a/lib/vagrant/action/builtin/mixin_synced_folders.rb +++ b/lib/vagrant/action/builtin/mixin_synced_folders.rb @@ -1,4 +1,5 @@ require "json" +require "set" require 'vagrant/util/scoped_hash_override' @@ -151,6 +152,49 @@ module Vagrant return folders end + # This finds the difference between two lists of synced folder + # definitions. + # + # This will return a hash with three keys: "added", "removed", + # and "modified". These will contain a set of IDs of folders + # that were added, removed, or modified, respectively. + # + # The parameters should be results from the {#synced_folders} call. + # + # @return [hash] + def synced_folders_diff(one, two) + existing_ids = {} + one.each do |impl, fs| + fs.each do |id, data| + existing_ids[id] = data + end + end + + result = Hash.new { |h, k| h[k] = Set.new } + two.each do |impl, fs| + fs.each do |id, data| + existing = existing_ids.delete(id) + if !existing + result[:added] << id + next + end + + # Exists, so we have to compare the host and guestpath, which + # is most important... + if existing[:hostpath] != data[:hostpath] || + existing[:guestpath] != data[:guestpath] + result[:modified] << id + end + end + end + + existing_ids.each do |k, _| + result[:removed] << k + end + + result + end + protected def cached_synced_folders(machine) diff --git a/test/unit/vagrant/action/builtin/mixin_synced_folders_test.rb b/test/unit/vagrant/action/builtin/mixin_synced_folders_test.rb index d588879b9..a9c4711d2 100644 --- a/test/unit/vagrant/action/builtin/mixin_synced_folders_test.rb +++ b/test/unit/vagrant/action/builtin/mixin_synced_folders_test.rb @@ -191,4 +191,64 @@ describe Vagrant::Action::Builtin::MixinSyncedFolders do }) end end + + describe "#synced_folders_diff" do + it "sees two equal " do + one = { + default: { "foo" => {} }, + } + + two = { + default: { "foo" => {} }, + } + + expect(subject.synced_folders_diff(one, two)).to be_empty + end + + it "sees modifications" do + one = { + default: { "foo" => {} }, + } + + two = { + default: { "foo" => { hostpath: "foo" } }, + } + + result = subject.synced_folders_diff(one, two) + expect(result[:modified]).to_not be_empty + end + + it "sees adding" do + one = { + default: { "foo" => {} }, + } + + two = { + default: { + "foo" => {}, + "bar" => {}, + }, + } + + result = subject.synced_folders_diff(one, two) + expect(result[:added]).to_not be_empty + expect(result[:removed]).to be_empty + expect(result[:modified]).to be_empty + end + + it "sees removing" do + one = { + default: { "foo" => {} }, + } + + two = { + default: {}, + } + + result = subject.synced_folders_diff(one, two) + expect(result[:added]).to be_empty + expect(result[:removed]).to_not be_empty + expect(result[:modified]).to be_empty + end + end end