sass 3.3.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/VERSION_DATE +1 -1
  4. data/lib/sass/importers/filesystem.rb +3 -3
  5. data/lib/sass/plugin/compiler.rb +95 -52
  6. data/lib/sass/script/functions.rb +1 -1
  7. data/lib/sass/source/map.rb +3 -3
  8. data/lib/sass/util.rb +16 -1
  9. data/vendor/listen/CHANGELOG.md +175 -35
  10. data/vendor/listen/Gemfile +5 -15
  11. data/vendor/listen/README.md +111 -77
  12. data/vendor/listen/Rakefile +0 -42
  13. data/vendor/listen/lib/listen.rb +33 -19
  14. data/vendor/listen/lib/listen/adapter.rb +193 -82
  15. data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
  16. data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
  17. data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
  18. data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
  19. data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
  20. data/vendor/listen/lib/listen/directory_record.rb +96 -61
  21. data/vendor/listen/lib/listen/listener.rb +135 -37
  22. data/vendor/listen/lib/listen/turnstile.rb +9 -5
  23. data/vendor/listen/lib/listen/version.rb +1 -1
  24. data/vendor/listen/listen.gemspec +6 -0
  25. data/vendor/listen/spec/listen/adapter_spec.rb +37 -82
  26. data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
  27. data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
  28. data/vendor/listen/spec/listen/listener_spec.rb +128 -39
  29. data/vendor/listen/spec/listen_spec.rb +15 -21
  30. data/vendor/listen/spec/spec_helper.rb +4 -0
  31. data/vendor/listen/spec/support/adapter_helper.rb +52 -15
  32. data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
  33. data/vendor/listen/spec/support/listeners_helper.rb +30 -7
  34. metadata +3 -23
  35. data/ext/mkrf_conf.rb +0 -27
  36. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  37. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  38. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  39. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
@@ -11,8 +11,10 @@ module Listen
11
11
  class DirectoryRecord
12
12
  attr_reader :directory, :paths, :sha1_checksums
13
13
 
14
- DEFAULT_IGNORED_DIRECTORIES = %w[.rbx .bundle .git .svn log tmp vendor]
14
+ # The default list of directories that get ignored by the listener.
15
+ DEFAULT_IGNORED_DIRECTORIES = %w[.rbx .bundle .git .svn bundle log tmp vendor]
15
16
 
17
+ # The default list of files that get ignored by the listener.
16
18
  DEFAULT_IGNORED_EXTENSIONS = %w[.DS_Store]
17
19
 
18
20
  # Defines the used precision based on the type of mtime returned by the
@@ -56,15 +58,14 @@ module Listen
56
58
  def initialize(directory)
57
59
  raise ArgumentError, "The path '#{directory}' is not a directory!" unless File.directory?(directory)
58
60
 
59
- @directory = directory
60
- @ignoring_patterns = Set.new
61
- @filtering_patterns = Set.new
62
- @sha1_checksums = Hash.new
61
+ @directory, @sha1_checksums = File.expand_path(directory), Hash.new
62
+ @ignoring_patterns, @filtering_patterns = Set.new, Set.new
63
63
 
64
64
  @ignoring_patterns.merge(DirectoryRecord.generate_default_ignoring_patterns)
65
65
  end
66
66
 
67
- # Returns the ignoring patterns in the record
67
+ # Returns the ignoring patterns in the record to know
68
+ # which paths should be ignored.
68
69
  #
69
70
  # @return [Array<Regexp>] the ignoring patterns
70
71
  #
@@ -72,7 +73,7 @@ module Listen
72
73
  @ignoring_patterns.to_a
73
74
  end
74
75
 
75
- # Returns the filtering patterns used in the record to know
76
+ # Returns the filtering patterns in the record to know
76
77
  # which paths should be stored.
77
78
  #
78
79
  # @return [Array<Regexp>] the filtering patterns
@@ -86,10 +87,10 @@ module Listen
86
87
  # @example Ignore some paths
87
88
  # ignore %r{^ignored/path/}, /man/
88
89
  #
89
- # @param [Regexp] regexp a pattern for ignoring paths
90
+ # @param [Regexp] regexps a list of patterns for ignoring paths
90
91
  #
91
92
  def ignore(*regexps)
92
- @ignoring_patterns.merge(regexps)
93
+ @ignoring_patterns.merge(regexps).reject! { |r| r.nil? }
93
94
  end
94
95
 
95
96
  # Replaces ignoring patterns in the record.
@@ -97,37 +98,37 @@ module Listen
97
98
  # @example Ignore only these paths
98
99
  # ignore! %r{^ignored/path/}, /man/
99
100
  #
100
- # @param [Regexp] regexp a pattern for ignoring paths
101
+ # @param [Regexp] regexps a list of patterns for ignoring paths
101
102
  #
102
103
  def ignore!(*regexps)
103
- @ignoring_patterns.replace(regexps)
104
+ @ignoring_patterns.replace(regexps).reject! { |r| r.nil? }
104
105
  end
105
106
 
106
- # Adds filtering patterns to the listener.
107
+ # Adds filtering patterns to the record.
107
108
  #
108
109
  # @example Filter some files
109
- # ignore /\.txt$/, /.*\.zip/
110
+ # filter /\.txt$/, /.*\.zip/
110
111
  #
111
- # @param [Regexp] regexp a pattern for filtering paths
112
+ # @param [Regexp] regexps a list of patterns for filtering files
112
113
  #
113
114
  def filter(*regexps)
114
- @filtering_patterns.merge(regexps)
115
+ @filtering_patterns.merge(regexps).reject! { |r| r.nil? }
115
116
  end
116
117
 
117
- # Replaces filtering patterns in the listener.
118
+ # Replaces filtering patterns in the record.
118
119
  #
119
120
  # @example Filter only these files
120
- # ignore /\.txt$/, /.*\.zip/
121
+ # filter! /\.txt$/, /.*\.zip/
121
122
  #
122
- # @param [Regexp] regexp a pattern for filtering paths
123
+ # @param [Regexp] regexps a list of patterns for filtering files
123
124
  #
124
125
  def filter!(*regexps)
125
- @filtering_patterns.replace(regexps)
126
+ @filtering_patterns.replace(regexps).reject! { |r| r.nil? }
126
127
  end
127
128
 
128
129
  # Returns whether a path should be ignored or not.
129
130
  #
130
- # @param [String] path the path to test.
131
+ # @param [String] path the path to test
131
132
  #
132
133
  # @return [Boolean]
133
134
  #
@@ -138,7 +139,7 @@ module Listen
138
139
 
139
140
  # Returns whether a path should be filtered or not.
140
141
  #
141
- # @param [String] path the path to test.
142
+ # @param [String] path the path to test
142
143
  #
143
144
  # @return [Boolean]
144
145
  #
@@ -159,9 +160,9 @@ module Listen
159
160
  end
160
161
 
161
162
  # Detects changes in the passed directories, updates
162
- # the record with the new changes and returns the changes
163
+ # the record with the new changes and returns the changes.
163
164
  #
164
- # @param [Array] directories the list of directories scan for changes
165
+ # @param [Array] directories the list of directories to scan for changes
165
166
  # @param [Hash] options
166
167
  # @option options [Boolean] recursive scan all sub-directories recursively
167
168
  # @option options [Boolean] relative_paths whether or not to use relative paths for changes
@@ -174,6 +175,7 @@ module Listen
174
175
 
175
176
  directories.each do |directory|
176
177
  next unless directory[@directory] # Path is or inside directory
178
+
177
179
  detect_modifications_and_removals(directory, options)
178
180
  detect_additions(directory, options)
179
181
  end
@@ -188,9 +190,15 @@ module Listen
188
190
  # @return [String] the relative path
189
191
  #
190
192
  def relative_to_base(path)
191
- return nil unless path[@directory]
192
- path = path.force_encoding("BINARY") if path.respond_to?(:force_encoding)
193
- path.sub(%r{^#{Regexp.quote(@directory)}#{File::SEPARATOR}?}, '')
193
+ path = path.dup
194
+ regexp = "\\A#{Regexp.quote directory}(#{File::SEPARATOR}|\\z)"
195
+ if path.respond_to?(:force_encoding)
196
+ path.force_encoding("BINARY")
197
+ regexp.force_encoding("BINARY")
198
+ end
199
+ if path.sub!(Regexp.new(regexp), '')
200
+ path
201
+ end
194
202
  end
195
203
 
196
204
  private
@@ -207,43 +215,69 @@ module Listen
207
215
  # @option options [Boolean] relative_paths whether or not to use relative paths for changes
208
216
  #
209
217
  def detect_modifications_and_removals(directory, options = {})
210
- @paths[directory].each do |basename, meta_data|
218
+ paths[directory].each do |basename, meta_data|
211
219
  path = File.join(directory, basename)
212
-
213
220
  case meta_data.type
214
221
  when 'Dir'
215
- if File.directory?(path)
216
- detect_modifications_and_removals(path, options) if options[:recursive]
217
- else
218
- detect_modifications_and_removals(path, { :recursive => true }.merge(options))
219
- @paths[directory].delete(basename)
220
- @paths.delete("#{directory}/#{basename}")
221
- end
222
+ detect_modification_or_removal_for_dir(path, options)
222
223
  when 'File'
223
- if File.exist?(path)
224
- new_mtime = mtime_of(path)
224
+ detect_modification_or_removal_for_file(path, meta_data, options)
225
+ end
226
+ end
227
+ end
225
228
 
226
- # First check if we are in the same second (to update checksums)
227
- # before checking the time difference
228
- if (meta_data.mtime.to_i == new_mtime.to_i && content_modified?(path)) || meta_data.mtime < new_mtime
229
- # Update the sha1 checksum of the file
230
- insert_sha1_checksum(path)
229
+ def detect_modification_or_removal_for_dir(path, options)
231
230
 
232
- # Update the meta data of the file
233
- meta_data.mtime = new_mtime
234
- @paths[directory][basename] = meta_data
231
+ # Directory still exists
232
+ if File.directory?(path)
233
+ detect_modifications_and_removals(path, options) if options[:recursive]
235
234
 
236
- @changes[:modified] << (options[:relative_paths] ? relative_to_base(path) : path)
237
- end
238
- else
239
- @paths[directory].delete(basename)
240
- @sha1_checksums.delete(path)
241
- @changes[:removed] << (options[:relative_paths] ? relative_to_base(path) : path)
242
- end
243
- end
235
+ # Directory has been removed
236
+ else
237
+ detect_modifications_and_removals(path, options)
238
+ @paths[File.dirname(path)].delete(File.basename(path))
239
+ @paths.delete("#{File.dirname(path)}/#{File.basename(path)}")
240
+ end
241
+ end
242
+
243
+ def detect_modification_or_removal_for_file(path, meta_data, options)
244
+ # File still exists
245
+ if File.exist?(path)
246
+ detect_modification(path, meta_data, options)
247
+
248
+ # File has been removed
249
+ else
250
+ removal_detected(path, meta_data, options)
251
+ end
252
+ end
253
+
254
+ def detect_modification(path, meta_data, options)
255
+ new_mtime = mtime_of(path)
256
+
257
+ # First check if we are in the same second (to update checksums)
258
+ # before checking the time difference
259
+ if (meta_data.mtime.to_i == new_mtime.to_i && content_modified?(path)) || meta_data.mtime < new_mtime
260
+ modification_detected(path, meta_data, new_mtime, options)
244
261
  end
245
262
  end
246
263
 
264
+ def modification_detected(path, meta_data, new_mtime, options)
265
+ # Update the sha1 checksum of the file
266
+ update_sha1_checksum(path)
267
+
268
+ # Update the meta data of the file
269
+ meta_data.mtime = new_mtime
270
+ @paths[File.dirname(path)][File.basename(path)] = meta_data
271
+
272
+ @changes[:modified] << (options[:relative_paths] ? relative_to_base(path) : path)
273
+ end
274
+
275
+ def removal_detected(path, meta_data, options)
276
+ @paths[File.dirname(path)].delete(File.basename(path))
277
+ @sha1_checksums.delete(path)
278
+ @changes[:removed] << (options[:relative_paths] ? relative_to_base(path) : path)
279
+ end
280
+
247
281
  # Detects additions in a directory.
248
282
  #
249
283
  # @param [String] directory the path to analyze
@@ -283,9 +317,10 @@ module Listen
283
317
  # @param [String] path the file path
284
318
  #
285
319
  def content_modified?(path)
320
+ return false unless File.ftype(path) == 'file'
286
321
  @sha1_checksum = sha1_checksum(path)
287
- if @sha1_checksums[path] == @sha1_checksum || !@sha1_checksums.key?(path)
288
- insert_sha1_checksum(path)
322
+ if sha1_checksums[path] == @sha1_checksum || !sha1_checksums.key?(path)
323
+ update_sha1_checksum(path)
289
324
  false
290
325
  else
291
326
  true
@@ -296,7 +331,7 @@ module Listen
296
331
  #
297
332
  # @param [String] path the SHA1-checksum path to insert in @sha1_checksums.
298
333
  #
299
- def insert_sha1_checksum(path)
334
+ def update_sha1_checksum(path)
300
335
  if @sha1_checksum ||= sha1_checksum(path)
301
336
  @sha1_checksums[path] = @sha1_checksum
302
337
  @sha1_checksum = nil
@@ -309,18 +344,18 @@ module Listen
309
344
  #
310
345
  def sha1_checksum(path)
311
346
  Digest::SHA1.file(path).to_s
312
- rescue Errno::EACCES, Errno::ENOENT, Errno::ENXIO, Errno::EOPNOTSUPP
347
+ rescue
313
348
  nil
314
349
  end
315
350
 
316
351
  # Traverses the base directory looking for paths that should
317
- # be stored; thus paths that are filters or not ignored.
352
+ # be stored; thus paths that are filtered or not ignored.
318
353
  #
319
354
  # @yield [path] an important path
320
355
  #
321
356
  def important_paths
322
- Find.find(@directory) do |path|
323
- next if path == @directory
357
+ Find.find(directory) do |path|
358
+ next if path == directory
324
359
 
325
360
  if File.directory?(path)
326
361
  # Add a trailing slash to directories when checking if a directory is
@@ -355,7 +390,7 @@ module Listen
355
390
  # @return [Boolean]
356
391
  #
357
392
  def existing_path?(path)
358
- @paths[File.dirname(path)][File.basename(path)] != nil
393
+ paths[File.dirname(path)][File.basename(path)] != nil
359
394
  end
360
395
 
361
396
  # Returns the modification time of a file based on the precision defined by the system
@@ -2,14 +2,18 @@ require 'pathname'
2
2
 
3
3
  module Listen
4
4
  class Listener
5
- attr_reader :directory, :directory_record, :adapter
5
+ attr_reader :directories, :directories_records, :block, :adapter, :adapter_options, :use_relative_paths
6
6
 
7
- # The default value for using relative paths in the callback.
8
- DEFAULT_TO_RELATIVE_PATHS = false
7
+ BLOCKING_PARAMETER_DEPRECATION_MESSAGE = <<-EOS.gsub(/^\s*/, '')
8
+ The blocking parameter of Listen::Listener#start is deprecated.\n
9
+ Please use Listen::Adapter#start for a non-blocking listener and Listen::Listener#start! for a blocking one.
10
+ EOS
9
11
 
10
- # Initializes the directory listener.
12
+ RELATIVE_PATHS_WITH_MULTIPLE_DIRECTORIES_WARNING_MESSAGE = "The relative_paths option doesn't work when listening to multiple diretories."
13
+
14
+ # Initializes the directories listener.
11
15
  #
12
- # @param [String] directory the directory to listen to
16
+ # @param [String] directory the directories to listen to
13
17
  # @param [Hash] options the listen options
14
18
  # @option options [Regexp] ignore a pattern for ignoring paths
15
19
  # @option options [Regexp] filter a pattern for filtering paths
@@ -17,42 +21,55 @@ module Listen
17
21
  # @option options [Boolean] relative_paths whether or not to use relative-paths in the callback
18
22
  # @option options [Boolean] force_polling whether to force the polling adapter or not
19
23
  # @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
24
+ # @option options [Class] force_adapter force the use of this adapter class, skipping usual adapter selection
20
25
  #
21
26
  # @yield [modified, added, removed] the changed files
22
27
  # @yieldparam [Array<String>] modified the list of modified files
23
28
  # @yieldparam [Array<String>] added the list of added files
24
29
  # @yieldparam [Array<String>] removed the list of removed files
25
30
  #
26
- def initialize(directory, options = {}, &block)
27
- @block = block
28
- @directory = Pathname.new(directory).realpath.to_s
29
- @directory_record = DirectoryRecord.new(@directory)
30
- @use_relative_paths = DEFAULT_TO_RELATIVE_PATHS
31
+ def initialize(*args, &block)
32
+ options = args.last.is_a?(Hash) ? args.pop : {}
33
+ directories = args.flatten
34
+ initialize_directories_and_directories_records(directories)
35
+ initialize_relative_paths_usage(options)
36
+ @block = block
31
37
 
32
- @use_relative_paths = options.delete(:relative_paths) if options[:relative_paths]
33
- @directory_record.ignore(*options.delete(:ignore)) if options[:ignore]
34
- @directory_record.filter(*options.delete(:filter)) if options[:filter]
38
+ ignore(*options.delete(:ignore))
39
+ filter(*options.delete(:filter))
35
40
 
36
41
  @adapter_options = options
37
42
  end
38
43
 
39
44
  # Starts the listener by initializing the adapter and building
40
45
  # the directory record concurrently, then it starts the adapter to watch
41
- # for changes.
46
+ # for changes. The current thread is not blocked after starting.
42
47
  #
43
- # @param [Boolean] blocking whether or not to block the current thread after starting
48
+ # @see Listen::Listener#start!
44
49
  #
45
- def start(blocking = true)
46
- t = Thread.new { @directory_record.build }
47
- @adapter = initialize_adapter
48
- t.join
49
- @adapter.start(blocking)
50
+ def start(deprecated_blocking = nil)
51
+ Kernel.warn "[Listen warning]:\n#{BLOCKING_PARAMETER_DEPRECATION_MESSAGE}" unless deprecated_blocking.nil?
52
+ setup
53
+ adapter.start
54
+ end
55
+
56
+ # Starts the listener by initializing the adapter and building
57
+ # the directory record concurrently, then it starts the adapter to watch
58
+ # for changes. The current thread is blocked after starting.
59
+ #
60
+ # @see Listen::Listener#start
61
+ #
62
+ # @since 1.0.0
63
+ #
64
+ def start!
65
+ setup
66
+ adapter.start!
50
67
  end
51
68
 
52
69
  # Stops the listener.
53
70
  #
54
71
  def stop
55
- @adapter.stop
72
+ adapter && adapter.stop
56
73
  end
57
74
 
58
75
  # Pauses the listener.
@@ -60,7 +77,7 @@ module Listen
60
77
  # @return [Listen::Listener] the listener
61
78
  #
62
79
  def pause
63
- @adapter.paused = true
80
+ adapter.pause
64
81
  self
65
82
  end
66
83
 
@@ -69,8 +86,8 @@ module Listen
69
86
  # @return [Listen::Listener] the listener
70
87
  #
71
88
  def unpause
72
- @directory_record.build
73
- @adapter.paused = false
89
+ build_directories_records
90
+ adapter.unpause
74
91
  self
75
92
  end
76
93
 
@@ -79,7 +96,7 @@ module Listen
79
96
  # @return [Boolean] adapter paused status
80
97
  #
81
98
  def paused?
82
- !!@adapter && @adapter.paused == true
99
+ !!adapter && adapter.paused?
83
100
  end
84
101
 
85
102
  # Adds ignoring patterns to the listener.
@@ -88,8 +105,10 @@ module Listen
88
105
  #
89
106
  # @return [Listen::Listener] the listener
90
107
  #
108
+ # @see Listen::DirectoryRecord#ignore
109
+ #
91
110
  def ignore(*regexps)
92
- @directory_record.ignore(*regexps)
111
+ directories_records.each { |r| r.ignore(*regexps) }
93
112
  self
94
113
  end
95
114
 
@@ -99,8 +118,10 @@ module Listen
99
118
  #
100
119
  # @return [Listen::Listener] the listener
101
120
  #
121
+ # @see Listen::DirectoryRecord#ignore!
122
+ #
102
123
  def ignore!(*regexps)
103
- @directory_record.ignore!(*regexps)
124
+ directories_records.each { |r| r.ignore!(*regexps) }
104
125
  self
105
126
  end
106
127
 
@@ -110,19 +131,23 @@ module Listen
110
131
  #
111
132
  # @return [Listen::Listener] the listener
112
133
  #
134
+ # @see Listen::DirectoryRecord#filter
135
+ #
113
136
  def filter(*regexps)
114
- @directory_record.filter(*regexps)
137
+ directories_records.each { |r| r.filter(*regexps) }
115
138
  self
116
139
  end
117
140
 
118
- # Replacing filtering patterns in the listener.
141
+ # Replaces filtering patterns in the listener.
119
142
  #
120
143
  # @param (see Listen::DirectoryRecord#filter!)
121
144
  #
122
145
  # @return [Listen::Listener] the listener
123
146
  #
147
+ # @see Listen::DirectoryRecord#filter!
148
+ #
124
149
  def filter!(*regexps)
125
- @directory_record.filter!(*regexps)
150
+ directories_records.each { |r| r.filter!(*regexps) }
126
151
  self
127
152
  end
128
153
 
@@ -156,6 +181,21 @@ module Listen
156
181
  self
157
182
  end
158
183
 
184
+ # Sets whether to force the use of a particular adapter, rather than
185
+ # going through usual adapter selection process on start.
186
+ #
187
+ # @example Force use of Linux polling
188
+ # force_adapter Listen::Adapters::Linux
189
+ #
190
+ # @param [Class] adapter class to use for file system event notification.
191
+ #
192
+ # @return [Listen::Listener] the listener
193
+ #
194
+ def force_adapter(adapter_class)
195
+ @adapter_options[:force_adapter] = adapter_class
196
+ self
197
+ end
198
+
159
199
  # Sets whether the paths in the callback should be
160
200
  # relative or absolute.
161
201
  #
@@ -171,7 +211,7 @@ module Listen
171
211
  self
172
212
  end
173
213
 
174
- # Defines a custom polling fallback message of disable it.
214
+ # Defines a custom polling fallback message or disable it.
175
215
  #
176
216
  # @example Disabling the polling fallback message
177
217
  # polling_fallback_message false
@@ -204,22 +244,80 @@ module Listen
204
244
  #
205
245
  # @param (see Listen::DirectoryRecord#fetch_changes)
206
246
  #
247
+ # @see Listen::DirectoryRecord#fetch_changes
248
+ #
207
249
  def on_change(directories, options = {})
208
- changes = @directory_record.fetch_changes(directories, options.merge(
209
- :relative_paths => @use_relative_paths
210
- ))
250
+ changes = fetch_records_changes(directories, options)
211
251
  unless changes.values.all? { |paths| paths.empty? }
212
- @block.call(changes[:modified],changes[:added],changes[:removed])
252
+ block.call(changes[:modified], changes[:added], changes[:removed])
213
253
  end
254
+ rescue => ex
255
+ Kernel.warn "[Listen warning]: Change block raise an execption: #{$!}"
256
+ Kernel.warn "Backtrace:\n\t#{ex.backtrace.join("\n\t")}"
214
257
  end
215
258
 
216
259
  private
217
260
 
261
+ # Initializes the directories to watch as well as the directories records.
262
+ #
263
+ # @see Listen::DirectoryRecord
264
+ #
265
+ def initialize_directories_and_directories_records(directories)
266
+ @directories = directories.map { |d| Pathname.new(d).realpath.to_s }
267
+ @directories_records = directories.map { |d| DirectoryRecord.new(d) }
268
+ end
269
+
270
+ # Initializes whether or not using relative paths.
271
+ #
272
+ def initialize_relative_paths_usage(options)
273
+ if directories.size > 1 && options[:relative_paths]
274
+ Kernel.warn "[Listen warning]: #{RELATIVE_PATHS_WITH_MULTIPLE_DIRECTORIES_WARNING_MESSAGE}"
275
+ end
276
+ @use_relative_paths = directories.one? && options.delete(:relative_paths) { false }
277
+ end
278
+
279
+ # Build the directory record concurrently and initialize the adapter.
280
+ #
281
+ def setup
282
+ t = Thread.new { build_directories_records }
283
+ @adapter = initialize_adapter
284
+ t.join
285
+ end
286
+
218
287
  # Initializes an adapter passing it the callback and adapters' options.
219
288
  #
220
289
  def initialize_adapter
221
- callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
222
- Adapter.select_and_initialize(@directory, @adapter_options, &callback)
290
+ callback = lambda { |changed_directories, options| self.on_change(changed_directories, options) }
291
+ Adapter.select_and_initialize(directories, adapter_options, &callback)
223
292
  end
293
+
294
+ # Build the watched directories' records.
295
+ #
296
+ def build_directories_records
297
+ directories_records.each { |r| r.build }
298
+ end
299
+
300
+ # Returns the sum of all the changes to the directories records
301
+ #
302
+ # @param (see Listen::DirectoryRecord#fetch_changes)
303
+ #
304
+ # @return [Hash] the changes
305
+ #
306
+ def fetch_records_changes(directories_to_search, options)
307
+ directories_records.inject({}) do |h, r|
308
+ # directory records skips paths outside their range, so passing the
309
+ # whole `directories` array is not a problem.
310
+ record_changes = r.fetch_changes(directories_to_search, options.merge(:relative_paths => use_relative_paths))
311
+
312
+ if h.empty?
313
+ h.merge!(record_changes)
314
+ else
315
+ h.each { |k, v| h[k] += record_changes[k] }
316
+ end
317
+
318
+ h
319
+ end
320
+ end
321
+
224
322
  end
225
323
  end