class Fig::UpdateLock

Public Class Methods

new(lock_directory, response) click to toggle source
# File lib/fig/update_lock.rb, line 10
def initialize(lock_directory, response)
  set_up_lock(lock_directory, response)

  return
end

Public Instance Methods

close() click to toggle source
# File lib/fig/update_lock.rb, line 16
def close()
  begin
    @lock.close
  rescue IOError => error
    # Don't care if it's already closed.
  end

  return
end

Private Instance Methods

raise_lock_usage_error(lock_directory) click to toggle source
# File lib/fig/update_lock.rb, line 82
  def raise_lock_usage_error(lock_directory)
    raise Fig::UserInputError.new(<<-END_MESSAGE)
Cannot update while another instance of Fig is updating #{lock_directory}.

You can tell Fig to wait for update with

    fig --update --update-lock-response wait ...

or you can throw caution to the wind with

    fig --update --update-lock-response ignore ...
    END_MESSAGE
  end
set_up_lock(lock_directory, response) click to toggle source
# File lib/fig/update_lock.rb, line 28
def set_up_lock(lock_directory, response)
  set_up_lock_file(lock_directory)

  should_warn = response ? false : true
  response ||= :wait

  if response == :wait
    if should_warn
      if ! @lock.flock(File::LOCK_EX | File::LOCK_NB)
        # Purposely ignoring standard logging setup so that this cannot be
        # turned off by "--log-level error".
        $stderr.puts(
          %Q<It looks like another instance of Fig is attempting to update #{lock_directory}. Will wait until it is done. (To suppress this warning in the future, explicitly specify "--update-lock-response wait".)>
        )

        @lock.flock(File::LOCK_EX)
      end
    else
      @lock.flock(File::LOCK_EX)
    end
  else
    if ! @lock.flock(File::LOCK_EX | File::LOCK_NB)
      raise_lock_usage_error(lock_directory)
    end
  end

  return
end
set_up_lock_file(lock_directory) click to toggle source
# File lib/fig/update_lock.rb, line 57
def set_up_lock_file(lock_directory)
  FileUtils.mkdir_p(lock_directory)

  # Tried using the directory itself as the lock, but Windows is
  # non-cooperative.
  lock_file = lock_directory + '/lock'

  # Yes, there's a race condition here, but with the way Windows file locking
  # works, it's better than a boot to the head.
  if ! File.exists? lock_file
    created_file = File.new(lock_file, 'w')
    created_file.close
  end

  @lock = File.new(lock_file, 'r+')

  # *sigh* Ruby 1.8 doesn't support close_on_exec(), but we'll still use it
  # if we can as a better attempt at safety.
  if @lock.respond_to? :close_on_exec=
    @lock.close_on_exec = true
  end

  return
end