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.



56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/file-monitor.rb', line 56

def initialize(project_dir = '.')
  @notifier    = INotify::Notifier.new
  @project_dir = project_dir

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

  @filters = {
    :files => FileMonitorFilter.new,
    :dirs => FileMonitorFilter.new 
  }
end

Class Method Details

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



242
243
244
245
246
# File 'lib/file-monitor.rb', line 242

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

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



248
249
250
# File 'lib/file-monitor.rb', line 248

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

Instance Method Details

#check(events) ⇒ Object

check the events received



212
213
214
215
216
217
# File 'lib/file-monitor.rb', line 212

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



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/file-monitor.rb', line 88

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



111
112
113
# File 'lib/file-monitor.rb', line 111

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

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



107
108
109
# File 'lib/file-monitor.rb', line 107

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

#frequency(*args) ⇒ Object



45
46
47
48
49
50
# File 'lib/file-monitor.rb', line 45

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



41
42
43
# File 'lib/file-monitor.rb', line 41

def frequency=(frequency)
  @frequency = frequency
end

#ignore_dirs(path) ⇒ Object

Compatible to old ignored_dirs and ignored_files mode



71
72
73
# File 'lib/file-monitor.rb', line 71

def ignore_dirs(path)
  self.ignored_dirs= path
end

#ignore_files(pattern) ⇒ Object



75
76
77
# File 'lib/file-monitor.rb', line 75

def ignore_files(pattern)
  self.ignored_files = pattern
end

#ignored_dir?(path) ⇒ Boolean

Returns:

  • (Boolean)


115
116
117
118
119
120
# File 'lib/file-monitor.rb', line 115

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

#ignored_dirs=(pattern) ⇒ Object



79
80
81
# File 'lib/file-monitor.rb', line 79

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

#ignored_file?(path) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#ignored_files=(pattern) ⇒ Object



83
84
85
# File 'lib/file-monitor.rb', line 83

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

#push_event(event) ⇒ Object



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

def push_event event
  @events << event
end

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

start watching if block given, check method will be ignored



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/file-monitor.rb', line 221

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

#set_frequency(frequency) ⇒ Object



52
53
54
# File 'lib/file-monitor.rb', line 52

def set_frequency(frequency)
  @frequency = frequency
end

#trim_dir(path) ⇒ Object



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

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

#watch(dir) ⇒ Object

Watch a directory



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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
# File 'lib/file-monitor.rb', line 138

def watch(dir)
  dir = trim_dir(dir)
  if ignored_dir?(dir)
    puts "ignore #{dir}"
    return false
  else
    puts "watching #{dir}"
  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

    if 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



200
201
202
203
204
205
206
207
208
209
# File 'lib/file-monitor.rb', line 200

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