Class: FileMonitor

Inherits:
Object
  • Object
show all
Defined in:
lib/file-monitor.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_dir = '.') ⇒ FileMonitor

Returns a new instance of FileMonitor.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 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

Class Method Details

.create(dir = '.', &block) ⇒ Object



268
269
270
271
272
# File 'lib/file-monitor.rb', line 268

def self.create(dir = '.', &block)
  m = FileMonitor.new(dir)
  m.instance_eval &block
  m
end

.watch(dir = '.', &block) ⇒ Object



274
275
276
# File 'lib/file-monitor.rb', line 274

def self.watch(dir = '.', &block)
  self.create(dir, &block)
end

Instance Method Details

#check(events) ⇒ Object

check the events received



238
239
240
241
242
243
# 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

#filter(type, args = [], &block) ⇒ Object

New Filter mode



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# 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) ⇒ Object Also known as: dirs



127
128
129
# File 'lib/file-monitor.rb', line 127

def filter_dirs(*args, &block)
  filter :dirs, args, &block
end

#filter_files(*args, &block) ⇒ Object Also known as: files



123
124
125
# File 'lib/file-monitor.rb', line 123

def filter_files(*args, &block)
  filter :files, args, &block
end


66
67
68
69
# File 'lib/file-monitor.rb', line 66

def follow_symlink(*args)
  @follow_symlink = args[0] if args.size()
  @follow_symlink
end

#follow_symlink=(follow_symlink) ⇒ Object

options



62
63
64
# File 'lib/file-monitor.rb', line 62

def follow_symlink=(follow_symlink)
  @follow_symlink = follow_symlink
end

#frequency(*args) ⇒ Object



54
55
56
57
58
59
# File 'lib/file-monitor.rb', line 54

def frequency(*args)
  if args.size()
    @frequency = args[0]
  end
  @frequency
end

#frequency=(frequency) ⇒ Object

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



50
51
52
# File 'lib/file-monitor.rb', line 50

def frequency=(frequency)
  @frequency = frequency
end

#ignore_dirs(path) ⇒ Object

Compatible to old ignored_dirs and ignored_files mode



87
88
89
# File 'lib/file-monitor.rb', line 87

def ignore_dirs(path)
  self.ignored_dirs= path
end

#ignore_files(pattern) ⇒ Object



91
92
93
# File 'lib/file-monitor.rb', line 91

def ignore_files(pattern)
  self.ignored_files = pattern
end

#ignored_dir?(path) ⇒ Boolean

Returns:

  • (Boolean)


131
132
133
134
135
136
# File 'lib/file-monitor.rb', line 131

def ignored_dir?(path)
  if path == '.'
    return false
  end
  @filters[:dirs].ignored? path
end

#ignored_dirs=(pattern) ⇒ Object



95
96
97
# File 'lib/file-monitor.rb', line 95

def ignored_dirs=(pattern)
  @filters[:dirs].disallow pattern
end

#ignored_file?(path) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/file-monitor.rb', line 138

def ignored_file?(path)
  @filters[:files].ignored? path
end

#ignored_files=(pattern) ⇒ Object



99
100
101
# File 'lib/file-monitor.rb', line 99

def ignored_files=(pattern)
  @filters[:files].disallow pattern
end

#push_event(event) ⇒ Object



142
143
144
# File 'lib/file-monitor.rb', line 142

def push_event event
  @events << event
end

#run(&block) ⇒ Object Also known as: exec

start watching if block given, check method will be ignored



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# 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

#trim_dir(path) ⇒ Object



146
147
148
149
150
151
# File 'lib/file-monitor.rb', line 146

def trim_dir(path)
  if path =~ /(.*)\/$/
    path = $1
  end
  path
end

#watch(dir) ⇒ Object

Watch a directory



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# 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) ⇒ Object

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



226
227
228
229
230
231
232
233
234
235
# 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