class FSEvent

Constants

VERSION

Attributes

callback[R]
paths[R]

Public Class Methods

new(args = nil, &block) click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 20
def initialize args = nil, &block
  watch(args, &block) unless args.nil?
end

Public Instance Methods

open_pipe() click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 106
def open_pipe
  IO.popen("'#{self.class.watcher_path}' #{options_string} #{shellescaped_paths}")
end
options_string() click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 112
def options_string
  @options.join(' ')
end
process_running?(pid) click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 96
def process_running?(pid)
  begin
    Process.kill(0, pid)
    true
  rescue Errno::ESRCH
    false
  end
end
run() click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 37
def run
  @pipe    = open_pipe
  @running = true

  # please note the use of IO::select() here, as it is used specifically to
  # preserve correct signal handling behavior in ruby 1.8.
  while @running && IO::select([@pipe], nil, nil, nil)
    # managing the IO ourselves allows us to be careful and never pass an
    # incomplete message to OTNetstring.parse()
    message = String.new
    length = String.new
    byte = nil

    reading_length = true
    found_length = false

    while reading_length
      byte = @pipe.read_nonblock(1)
      if "#{byte}" =~ /\d/
        length << byte
        found_length = true
      elsif found_length == false
        next
      else
        reading_length = false
      end
    end
    length = Integer(length, 10)
    type = byte

    message << "#{length}#{type}"
    message << @pipe.read(length)

    decoded = OTNetstring.parse(message)
    modified_paths = decoded["events"].map {|event| event["path"]}
    # passing the full info as a second block param feels icky, but such is
    # the trap of backward compatibility.
    case callback.arity
      when 1
        callback.call(modified_paths)
      when 2
        callback.call(modified_paths, decoded)
    end
  end
rescue Interrupt, IOError, Errno::EBADF
ensure
  stop
end
shellescape(str) click to toggle source

for Ruby 1.8.6 support

# File lib/rb-fsevent/fsevent.rb, line 121
def shellescape(str)
  # An empty argument will be skipped, so return empty quotes.
  return "''" if str.empty?

  str = str.dup

  # Process as a single byte sequence because not all shell
  # implementations are multibyte aware.
  str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1")

  # A LF cannot be escaped with a backslash because a backslash + LF
  # combo is regarded as line continuation and simply ignored.
  str.gsub!(/\n/, "'\n'")

  return str
end
shellescaped_paths() click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 116
def shellescaped_paths
  @paths.map {|path| shellescape(path)}.join(' ')
end
stop() click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 86
def stop
  unless @pipe.nil?
    Process.kill('KILL', @pipe.pid) if process_running?(@pipe.pid)
    @pipe.close
  end
rescue IOError, Errno::EBADF
ensure
  @running = false
end
watch(watch_paths, options=nil, &block) click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 24
def watch(watch_paths, options=nil, &block)
  @paths      = watch_paths.kind_of?(Array) ? watch_paths : [watch_paths]
  @callback   = block

  if options.kind_of?(Hash)
    @options  = parse_options(options)
  elsif options.kind_of?(Array)
    @options  = options
  else
    @options  = []
  end
end

Private Instance Methods

parse_options(options={}) click to toggle source
# File lib/rb-fsevent/fsevent.rb, line 145
def parse_options(options={})
  opts = ['--format=otnetstring']
  opts.concat(['--since-when', options[:since_when]]) if options[:since_when]
  opts.concat(['--latency', options[:latency]]) if options[:latency]
  opts.push('--no-defer') if options[:no_defer]
  opts.push('--watch-root') if options[:watch_root]
  opts.push('--file-events') if options[:file_events]
  # ruby 1.9's IO.popen(array-of-stuff) syntax requires all items to be strings
  opts.map {|opt| "#{opt}"}
end