core: MachineIndex updates existing entry if name, provider, path match

This commit is contained in:
Mitchell Hashimoto 2014-04-14 19:09:36 -07:00
parent d72c18a8b1
commit 9b22ccbd32
2 changed files with 67 additions and 18 deletions

View File

@ -171,27 +171,40 @@ module Vagrant
id = entry.id
@lock.synchronize do
# Verify the machine is locked so we can safely write
# to it.
if !id
id = SecureRandom.uuid.gsub("-", "")
lock_file = lock_machine(id)
if !lock_file
raise "Failed to lock new machine: #{entry.name}"
with_index_lock do
# Reload so we have the latest machine data. This allows other
# processes to update their own machines without conflicting
# with our own.
unlocked_reload
# If we don't have a machine ID, try to look one up
if !id
self.each do |other|
if entry.name == other.name &&
entry.provider == other.provider &&
entry.vagrantfile_path.to_s == other.vagrantfile_path.to_s
id = other.id
break
end
end
# If we still don't have an ID, generate a random one
id = SecureRandom.uuid.gsub("-", "") if !id
# Get a lock on this machine
lock_file = lock_machine(id)
if !lock_file
raise "Failed to lock new machine: #{entry.name}"
end
@machine_locks[id] = lock_file
end
@machine_locks[id] = lock_file
end
if !@machine_locks[id]
raise "Unlocked write on machine: #{id}"
end
if !@machine_locks[id]
raise "Unlocked write on machine: #{id}"
end
with_index_lock do
# Reload so we have the latest machine data, then update
# this particular machine, then write. This allows other processes
# to update their own machines without conflicting with our own.
unlocked_reload
# Set our machine and save
@machines[id] = struct
unlocked_save
end
@ -218,6 +231,8 @@ module Vagrant
#
# If the lock cannot be acquired, then nil is returned.
#
# This should be called within an index lock.
#
# @return [File]
def lock_machine(uuid)
lock_path = @data_dir.join("#{uuid}.lock")

View File

@ -227,5 +227,39 @@ describe Vagrant::MachineIndex do
"foo" => "bar",
})
end
it "updates an existing directory if the name, provider, and path are the same" do
entry = entry_klass.new
entry.name = "foo"
entry.provider = "bar"
entry.vagrantfile_path = "/bar"
entry.state = "foo"
result = subject.set(entry)
expect(result.id).to_not be_empty
# Release it so we can modify it
subject.release(result)
entry2 = entry_klass.new
entry2.name = entry.name
entry2.provider = entry.provider
entry2.vagrantfile_path = entry.vagrantfile_path
entry2.state = "bar"
expect(entry2.id).to be_nil
nextresult = subject.set(entry2)
expect(nextresult.id).to eq(result.id)
# Release it so we can test the contents
subject.release(nextresult)
# Get it from a new class and check the results
subject = described_class.new(data_dir)
entry = subject.get(result.id)
expect(entry).to_not be_nil
expect(entry.name).to eq(entry2.name)
expect(entry.state).to eq(entry2.state)
end
end
end