class Rerun::Watcher

Constants

CREATED
DELETED
MODIFIED

Attributes

directories[R]
priority[RW]
sleep_time[RW]

Public Class Methods

new(&client_callback) click to toggle source
# File lib/rerun/watcher.rb, line 18
def initialize(&client_callback)
  @client_callback = client_callback

  @sleep_time = 1
  @priority = 0

  @directories = []
  @files = []

  @found = nil
  @first_time = true
  @thread = nil

end

Public Instance Methods

add_directory(dir, expression="**/*") click to toggle source

add a directory to be watched @param dir the directory to watch @param expression the glob pattern to search under the watched directory

# File lib/rerun/watcher.rb, line 36
def add_directory(dir, expression="**/*")
  if FileTest.exists?(dir) && FileTest.readable?(dir) then
    @directories << Directory.new(dir, expression)
  else
    raise InvalidDirectoryError, "Dir '#{dir}' either doesnt exist or isnt readable"
  end
end
add_file(file) click to toggle source

add a specific file to the watch list @param file the file to watch

# File lib/rerun/watcher.rb, line 50
def add_file(file)
  if FileTest.exists?(file) && FileTest.readable?(file) then
    @files << file
  else
    raise InvalidFileError, "File '#{file}' either doesnt exist or isnt readable"
  end
end
join() click to toggle source

wait for the filewatcher to finish

# File lib/rerun/watcher.rb, line 104
def join
  @thread.join() if @thread
rescue Interrupt => e
  # don't care
end
prime() click to toggle source
# File lib/rerun/watcher.rb, line 62
def prime
  @first_time = true
  @found = Hash.new()
  examine
  @first_time = false
end
remove_directory(dir) click to toggle source
# File lib/rerun/watcher.rb, line 44
def remove_directory(dir)
  @directories.delete(dir)
end
remove_file(file) click to toggle source
# File lib/rerun/watcher.rb, line 58
def remove_file(file)
  @files.delete(file)
end
start() click to toggle source
# File lib/rerun/watcher.rb, line 69
def start
  if @thread then
    raise RuntimeError, "already started"
  end

  prime

  @thread = Thread.new do
    while true do
      examine
      sleep(@sleep_time)
    end
  end

  @thread.priority = @priority

  at_exit { stop } #?

end
stop() click to toggle source

kill the filewatcher thread

# File lib/rerun/watcher.rb, line 90
def stop
  begin
    @thread.wakeup
  rescue ThreadError => e
    # ignore
  end
  begin
    @thread.kill
  rescue ThreadError => e
    # ignore
  end
end

Private Instance Methods

examine() click to toggle source
# File lib/rerun/watcher.rb, line 112
def examine
  already_examined = Hash.new()

  @directories.each do |directory|
    examine_files(directory.files(), already_examined)
  end

  examine_files(@files, already_examined) if not @files.empty?

  # now diff the found files and the examined files to see if
  # something has been deleted
  all_found_files = @found.keys()
  all_examined_files = already_examined.keys()
  intersection = all_found_files - all_examined_files
  intersection.each do |file_name|
    @client_callback.call(DELETED, file_name)
    @found.delete(file_name)
  end

end
examine_files(files, already_examined) click to toggle source

loops over the file list check for new or modified files

# File lib/rerun/watcher.rb, line 134
def examine_files(files, already_examined)
  files.each do |file_name|
    # expand the file name to the fully qual path
    full_file_name = File.expand_path(file_name)

    # we cant do much if the file isnt readable anyway
    if File.readable?(full_file_name) then
      already_examined[full_file_name] = true
      stat = File.stat(full_file_name)
      mod_time = stat.mtime
      size = stat.size

      # on the first iteration just load all of the files into the foundList
      if @first_time then
        @found[full_file_name] = FoundFile.new(full_file_name, mod_time, size)
      else
        # see if we have found this file already
        found_file = @found[full_file_name]
        @found[full_file_name] = FoundFile.new(full_file_name, mod_time, size)

        if found_file
          if mod_time > found_file.mod_time || size != found_file.size then
            @client_callback.call(MODIFIED, full_file_name)
          end
        else
          @client_callback.call(CREATED, full_file_name)
        end
      end
    end
  end
end