class FileMonitor

Public Class Methods

create(dir = '.', &block) click to toggle source
# File lib/file-monitor.rb, line 268
def self.create(dir = '.', &block)
  m = FileMonitor.new(dir)
  m.instance_eval &block
  m
end
new(project_dir = '.') click to toggle source
# File lib/file-monitor.rb, line 71
def initialize(project_dir = '.')
  @notifier    = INotify::Notifier.new
  @project_dir = project_dir

  @events         = []
  @ignores        = []
  @frequency      = 0.2
  @follow_symlink = false

  @filters = {
    :files => FileMonitorFilter.new,
    :dirs => FileMonitorFilter.new 
  }
end
watch(dir = '.', &block) click to toggle source
# File lib/file-monitor.rb, line 274
def self.watch(dir = '.', &block)
  self.create(dir, &block)
end

Public Instance Methods

check(events) click to toggle source

check the events received

# File lib/file-monitor.rb, line 238
def check(events)
  if !@check_warning_notified
    puts "[NOTICE] Inherit from FileMonitor and override method check(events) or\n         use file_monitor_instance.run do|events| end to do anything when any file changes"
    @check_warning_notified = true
  end
end
dirs(*args, &block)
Alias for: filter_dirs
exec(&block)
Alias for: run
files(*args, &block)
Alias for: filter_files
filter(type, args = [], &block) click to toggle source

New Filter mode

# File lib/file-monitor.rb, line 104
def filter(type, args = [], &block)
  @filters[type].reset()
  if block_given?
    if args.size() > 0
      $stderr.puts "filter's params #{args.to_s} has been ignored for the block is given"
    end
    @filters[type].instance_eval &block
  elsif args.size()
    @filters[type].instance_eval do
      disallow //
      for arg in args
        allow arg
      end
    end
  else
    raise 'filter needs params or block'
  end
end
filter_dirs(*args, &block) click to toggle source
# File lib/file-monitor.rb, line 127
def filter_dirs(*args, &block)
  filter :dirs, args, &block
end
Also aliased as: dirs
filter_files(*args, &block) click to toggle source
# File lib/file-monitor.rb, line 123
def filter_files(*args, &block)
  filter :files, args, &block
end
Also aliased as: files
frequency(*args) click to toggle source
# File lib/file-monitor.rb, line 54
def frequency(*args)
  if args.size()
    @frequency = args[0]
  end
  @frequency
end
frequency=(frequency) click to toggle source

do the action every @frequency second, to avoid check too frequently

# File lib/file-monitor.rb, line 50
def frequency=(frequency)
  @frequency = frequency
end
ignore_dirs(path) click to toggle source

Compatible to old ignored_dirs and ignored_files mode

# File lib/file-monitor.rb, line 87
def ignore_dirs(path)
  self.ignored_dirs= path
end
ignore_files(pattern) click to toggle source
# File lib/file-monitor.rb, line 91
def ignore_files(pattern)
  self.ignored_files = pattern
end
ignored_dir?(path) click to toggle source
# File lib/file-monitor.rb, line 131
def ignored_dir?(path)
  if path == '.'
    return false
  end
  @filters[:dirs].ignored? path
end
ignored_dirs=(pattern) click to toggle source
# File lib/file-monitor.rb, line 95
def ignored_dirs=(pattern)
  @filters[:dirs].disallow pattern
end
ignored_file?(path) click to toggle source
# File lib/file-monitor.rb, line 138
def ignored_file?(path)
  @filters[:files].ignored? path
end
ignored_files=(pattern) click to toggle source
# File lib/file-monitor.rb, line 99
def ignored_files=(pattern)
  @filters[:files].disallow pattern
end
push_event(event) click to toggle source
# File lib/file-monitor.rb, line 142
def push_event event
  @events << event
end
run() { |events| ... } click to toggle source

start watching if block given, check method will be ignored

# File lib/file-monitor.rb, line 247
def run(&block)
  watch_recursive @project_dir

  while true
    if IO.select([@notifier.to_io], [], [], @frequency)
      @notifier.process
    elsif @events.size > 0
      if block_given?
        yield @events
      else
        check @events
      end
      @events = []
    end
  end
end
Also aliased as: exec
trim_dir(path) click to toggle source
# File lib/file-monitor.rb, line 146
def trim_dir(path)
  if path =~ /(.*)\/$/
    path = $1
  end
  path
end
watch(dir) click to toggle source

Watch a directory

# File lib/file-monitor.rb, line 155
def watch(dir)
  # always allow watching @project_dir
  if dir != @project_dir
    dir = trim_dir(dir)
    if !@follow_symlink and File.symlink? dir
      puts "ignore symlink directory #{dir}"
      return false
    end
    if ignored_dir?(dir)
      puts "ignore #{dir}"
      return false
    else
      puts "watching #{dir}"
    end
  end

  @notifier.watch dir, :modify, :create, :move, :delete, :onlydir do|event|
    flags = event.flags

    # display event info
    # + created or moved_to
    # - deleted or moved_from
    # # modified
    # 'stop watching' ignored
    info = ''
    flag = flags[0]
    flag = :moved_from if flags.include? :moved_from
    flag = :moved_to   if flags.include? :moved_to

    case flag
    when :moved_from, :delete
      info += '-'
    when :moved_to, :create
      info += '+'
    when :modify
      info += '#'
    when :ignored
      info += 'stop watching'
    else
      info += 'unknown ' + flags.to_s
    end

    is_dir = flags.include?(:isdir)
    if is_dir and ignored_dir?(event.absolute_name) or 
      !is_dir and ignored_file?(event.absolute_name)
      # the ignored info will not put currently
      info += "i #{event.absolute_name}"
      next
    else
      info += "  #{event.absolute_name}"
      puts info
    end

    if flags.include? :isdir
      if flags.include? :ignore?
        @notifier.watchers.delete watcher.id
      elsif flags.include? :create or flags.include? :move
        watch_recursive event.absolute_name
      else
        push_event event
      end
    else
      push_event event
    end
  end

  return true
end
watch_recursive(dir) click to toggle source

Watch directory recursive use our recursive instead rb-inotify’s :recursive to filter the directory

# File lib/file-monitor.rb, line 226
def watch_recursive(dir)
  if watch dir
    # if watch current directory succeeded, then continue watching the sub-directories
    Dir.glob(File.join(dir, "*/"), File::FNM_DOTMATCH).each do|subdir|
      name = File.basename(subdir)
      next if name == ".." or name == "."
      watch_recursive subdir
    end
  end
end