sass 3.2.5 → 3.2.6

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 (56) hide show
  1. data/VERSION +1 -1
  2. data/VERSION_DATE +1 -1
  3. data/bin/sass +2 -1
  4. data/bin/sass-convert +2 -1
  5. data/bin/scss +2 -1
  6. data/lib/sass/cache_stores/chain.rb +1 -1
  7. data/lib/sass/cache_stores/filesystem.rb +0 -1
  8. data/lib/sass/engine.rb +7 -1
  9. data/lib/sass/importers/filesystem.rb +1 -1
  10. data/lib/sass/media.rb +1 -4
  11. data/lib/sass/script/funcall.rb +43 -8
  12. data/lib/sass/script/lexer.rb +0 -2
  13. data/lib/sass/script/parser.rb +0 -2
  14. data/lib/sass/scss/parser.rb +13 -1
  15. data/lib/sass/selector/simple_sequence.rb +1 -1
  16. data/lib/sass/tree/comment_node.rb +2 -2
  17. data/lib/sass/tree/visitors/cssize.rb +10 -1
  18. data/lib/sass/tree/visitors/perform.rb +4 -2
  19. data/lib/sass/util.rb +54 -1
  20. data/lib/sass/util/multibyte_string_scanner.rb +29 -8
  21. data/test/sass/engine_test.rb +16 -0
  22. data/test/sass/extend_test.rb +15 -0
  23. data/test/sass/script_test.rb +3 -1
  24. data/vendor/listen/CHANGELOG.md +76 -2
  25. data/vendor/listen/CONTRIBUTING.md +38 -0
  26. data/vendor/listen/Gemfile +8 -1
  27. data/vendor/listen/Guardfile +1 -1
  28. data/vendor/listen/LICENSE +1 -1
  29. data/vendor/listen/README.md +8 -5
  30. data/vendor/listen/lib/listen.rb +7 -5
  31. data/vendor/listen/lib/listen/adapter.rb +76 -29
  32. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  33. data/vendor/listen/lib/listen/adapters/darwin.rb +11 -10
  34. data/vendor/listen/lib/listen/adapters/linux.rb +33 -30
  35. data/vendor/listen/lib/listen/adapters/polling.rb +2 -1
  36. data/vendor/listen/lib/listen/adapters/windows.rb +27 -21
  37. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  38. data/vendor/listen/lib/listen/directory_record.rb +63 -10
  39. data/vendor/listen/lib/listen/listener.rb +22 -0
  40. data/vendor/listen/lib/listen/multi_listener.rb +22 -0
  41. data/vendor/listen/lib/listen/version.rb +1 -1
  42. data/vendor/listen/listen.gemspec +0 -4
  43. data/vendor/listen/spec/listen/adapter_spec.rb +45 -4
  44. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  45. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +6 -0
  46. data/vendor/listen/spec/listen/adapters/linux_spec.rb +6 -0
  47. data/vendor/listen/spec/listen/adapters/windows_spec.rb +7 -1
  48. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  49. data/vendor/listen/spec/listen/directory_record_spec.rb +91 -4
  50. data/vendor/listen/spec/listen/listener_spec.rb +14 -0
  51. data/vendor/listen/spec/listen/multi_listener_spec.rb +19 -1
  52. data/vendor/listen/spec/spec_helper.rb +6 -3
  53. data/vendor/listen/spec/support/adapter_helper.rb +125 -212
  54. data/vendor/listen/spec/support/listeners_helper.rb +13 -1
  55. data/vendor/listen/spec/support/platform_helper.rb +4 -0
  56. metadata +9 -3
@@ -493,7 +493,9 @@ SASS
493
493
  # argument errors caused by programming errors in a function and
494
494
  # argument errors explicitly thrown within that function.
495
495
  return if RUBY_PLATFORM =~ /java/
496
- assert_raise_message(ArgumentError, 'wrong number of arguments (0 for 1)') {resolve("arg-error()")}
496
+
497
+ # Don't validate the message; it's different on Rubinius.
498
+ assert_raise(ArgumentError) {resolve("arg-error()")}
497
499
  end
498
500
 
499
501
  def test_shallow_argument_error_unwrapped
@@ -1,3 +1,62 @@
1
+ ## 0.7.2 - January 11, 2013
2
+
3
+ ### Bug fix
4
+
5
+ - [#76] Exception on filename which is not in UTF-8. (fixed by [@piotr-sokolowski][])
6
+
7
+ ## 0.7.1 - January 6, 2013
8
+
9
+ ### Bug fix
10
+
11
+ - [#75] Default high precision off if the mtime call fails. (fixed by [@zanker][])
12
+
13
+ ## 0.7.0 - December 29, 2012
14
+
15
+ ### Bug fixes
16
+
17
+ - [#73] Rescue Errno::EOPNOTSUPP on sha1_checksum generation. (fixed by [@thibaudgg][])
18
+
19
+ ### New feature
20
+
21
+ - Add support for *BSD with rb-kqueue. ([@mat813][])
22
+
23
+ ## 0.6.0 - November 21, 2012
24
+
25
+ ### New feature
26
+
27
+ - Add bang versions for filter and ignore listener methods. ([@tarsolya][])
28
+
29
+ ## 0.5.3 - October 3, 2012
30
+
31
+ ### Bug fixes
32
+
33
+ - [#65] Fix ruby warning in adapter.rb. (fixed by [@vongruenigen][])
34
+ - [#64] ENXIO raised when hashing UNIX domain socket file. (fixed by [@sunaku][])
35
+
36
+ ## 0.5.2 - Septemper 23, 2012
37
+
38
+ ### Bug fix
39
+
40
+ - [#62] Fix double change callback with polling adapter. (fixed by [@thibaudgg][])
41
+
42
+ ## 0.5.1 - Septemper 18, 2012
43
+
44
+ ### Bug fix
45
+
46
+ - [#61] Fix a synchronisation bug that caused constant fallback to polling. (fixed by [@Maher4Ever][])
47
+
48
+ ## 0.5.0 - Septemper 1, 2012
49
+
50
+ ### New features
51
+
52
+ - Add a dependency manager to handle platform-specific gems. So there is no need anymore to install
53
+ extra gems which will never be used on the user system. ([@Maher4Ever][])
54
+ - Add a manual reporting mode to the adapters. ([@Maher4Ever][])
55
+
56
+ ### Improvements
57
+
58
+ - [#28] Enhance the speed of detecting changes on Windows by using the [WDM][] library. ([@Maher4Ever][])
59
+
1
60
  ## 0.4.7 - June 27, 2012
2
61
 
3
62
  ### Bug fixes
@@ -128,8 +187,16 @@
128
187
  [#21]: https://github.com/guard/listen/issues/21
129
188
  [#24]: https://github.com/guard/listen/issues/24
130
189
  [#27]: https://github.com/guard/listen/issues/27
190
+ [#28]: https://github.com/guard/listen/issues/28
131
191
  [#32]: https://github.com/guard/listen/issues/32
132
- [#39]: https://github.com/guard/listen/issues/39
192
+ [#41]: https://github.com/guard/listen/issues/41
193
+ [#61]: https://github.com/guard/listen/issues/61
194
+ [#62]: https://github.com/guard/listen/issues/62
195
+ [#64]: https://github.com/guard/listen/issues/64
196
+ [#65]: https://github.com/guard/listen/issues/65
197
+ [#73]: https://github.com/guard/listen/issues/73
198
+ [#75]: https://github.com/guard/listen/issues/75
199
+ [#76]: https://github.com/guard/listen/issues/76
133
200
  [@Maher4Ever]: https://github.com/Maher4Ever
134
201
  [@dkubb]: https://github.com/dkubb
135
202
  [@ebroder]: https://github.com/ebroder
@@ -138,10 +205,17 @@
138
205
  [@daemonza]: https://github.com/daemonza
139
206
  [@fny]: https://github.com/fny
140
207
  [@markiz]: https://github.com/markiz
208
+ [@mat813]: https://github.com/mat813
141
209
  [@napcs]: https://github.com/napcs
142
210
  [@netzpirat]: https://github.com/netzpirat
143
211
  [@nex3]: https://github.com/nex3
212
+ [@piotr-sokolowski]: https://github.com/piotr-sokolowski
144
213
  [@rymai]: https://github.com/rymai
145
214
  [@scottdavis]: https://github.com/scottdavis
215
+ [@sunaku]: https://github.com/sunaku
146
216
  [@textgoeshere]: https://github.com/textgoeshere
147
- [@thibaudgg]: https://github.com/thibaudgg
217
+ [@thibaudgg]: https://github.com/thibaudgg
218
+ [@tarsolya]: https://github.com/tarsolya
219
+ [@vongruenigen]: https://github.com/vongruenigen
220
+ [@zanker]: https://github.com/zanker
221
+ [WDM]: https://github.com/Maher4Ever/wdm
@@ -0,0 +1,38 @@
1
+ Contribute to Listen
2
+ ===================
3
+
4
+ File an issue
5
+ -------------
6
+
7
+ You can report bugs and feature requests to [GitHub Issues](https://github.com/guard/listen/issues).
8
+
9
+ **Please don't ask question in the issue tracker**, instead ask them in our
10
+ [Google group](http://groups.google.com/group/guard-dev) or on `#guard` (irc.freenode.net).
11
+
12
+ Try to figure out where the issue belongs to: Is it an issue with Listen itself or with Guard?
13
+
14
+ When you file a bug, please try to follow these simple rules if applicable:
15
+
16
+ * Make sure you run Listen with `bundle exec` first.
17
+ * Add your `Guardfile` (if used) and `Gemfile` to the issue.
18
+ * Make sure that the issue is reproducible with your description.
19
+
20
+ **It's most likely that your bug gets resolved faster if you provide as much information as possible!**
21
+
22
+ Development
23
+ -----------
24
+
25
+ * Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/listen/master/frames).
26
+ * Source hosted at [GitHub](https://github.com/guard/listen).
27
+
28
+ Pull requests are very welcome! Please try to follow these simple rules if applicable:
29
+
30
+ * Please create a topic branch for every separate change you make.
31
+ * Make sure your patches are well tested. All specs run with `rake spec` must pass.
32
+ * Update the [Yard](http://yardoc.org/) documentation.
33
+ * Update the [README](https://github.com/guard/listen/blob/master/README.md).
34
+ * Update the [CHANGELOG](https://github.com/guard/listen/blob/master/CHANGELOG.md) for noteworthy changes.
35
+ * Please **do not change** the version number.
36
+
37
+ For questions please join us in our [Google group](http://groups.google.com/group/guard-dev) or on
38
+ `#guard` (irc.freenode.net).
@@ -1,9 +1,16 @@
1
+ require 'rbconfig'
2
+
1
3
  source :rubygems
2
4
 
3
5
  gemspec
4
6
 
5
7
  gem 'rake'
6
8
 
9
+ gem 'rb-kqueue', '~> 0.2' if RbConfig::CONFIG['target_os'] =~ /freebsd/i
10
+ gem 'rb-fsevent', '~> 0.9.1' if RbConfig::CONFIG['target_os'] =~ /darwin(1.+)?$/i
11
+ gem 'rb-inotify', '~> 0.8.8', :github => 'mbj/rb-inotify' if RbConfig::CONFIG['target_os'] =~ /linux/i
12
+ gem 'wdm', '~> 0.0.3' if RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
13
+
7
14
  group :development do
8
15
  platform :ruby do
9
16
  gem 'coolline'
@@ -20,4 +27,4 @@ end
20
27
 
21
28
  group :test do
22
29
  gem 'rspec'
23
- end
30
+ end
@@ -1,4 +1,4 @@
1
- guard :rspec, :all_on_start => false, :all_after_pass => false, :cli => '--fail-fast --format doc' do
1
+ guard :rspec, :all_on_start => false, :all_after_pass => false do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
3
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
4
  watch('spec/support/adapter_helper.rb') { "spec/listen/adapters" }
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 Thibaud Guillaume-Gentil
1
+ Copyright (c) 2013 Thibaud Guillaume-Gentil
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -6,10 +6,10 @@ The Listen gem listens to file modifications and notifies you about the changes.
6
6
 
7
7
  * Works everywhere!
8
8
  * Supports watching multiple directories from a single listener.
9
- * OS-specific adapters for Mac OS X 10.6+, Linux and Windows.
9
+ * OS-specific adapters for Mac OS X 10.6+, Linux, *BSD and Windows.
10
10
  * Automatic fallback to polling if OS-specific adapter doesn't work.
11
- * Detects files modification, addidation and removal.
12
- * Checksum comparaison for modifications made under the same second.
11
+ * Detects file modification, addition and removal.
12
+ * Checksum comparison for modifications made under the same second.
13
13
  * Allows supplying regexp-patterns to ignore and filter paths for better results.
14
14
  * Tested on all Ruby environments via [travis-ci](http://travis-ci.org/guard/listen).
15
15
 
@@ -215,6 +215,8 @@ with a directory-separator, otherwise they won't work as expected.
215
215
  As an example: to ignore the `build` directory in a C-project, use `%r{build/}`
216
216
  and not `%r{/build/}`.
217
217
 
218
+ Use `#filter!` and `#ignore!` methods to overwrites default patterns.
219
+
218
220
  ### Non-blocking listening to changes
219
221
 
220
222
  Starting a listener blocks the current thread by default. That means any code after the
@@ -240,7 +242,7 @@ block execution. See the "Block API" section for an example.
240
242
  ## Listen adapters
241
243
 
242
244
  The Listen gem has a set of adapters to notify it when there are changes.
243
- There are 3 OS-specific adapters to support Mac, Linux and Windows. These adapters are fast
245
+ There are 3 OS-specific adapters to support Mac, Linux, *BSD and Windows. These adapters are fast
244
246
  as they use some system-calls to implement the notifying function.
245
247
 
246
248
  There is also a polling adapter which is a cross-platform adapter and it will
@@ -251,7 +253,6 @@ want to force the use of the polling adapter, either use the `:force_polling` op
251
253
  while initializing the listener or call the `force_polling` method on your listener
252
254
  before starting it.
253
255
 
254
- <a name="fallback"/>
255
256
  ## Polling fallback
256
257
 
257
258
  When a OS-specific adapter doesn't work the Listen gem automatically falls back to the polling adapter.
@@ -286,6 +287,7 @@ For questions please join us in our [Google group](http://groups.google.com/grou
286
287
  * [Michael Kessler (netzpirat)][] for having written the [initial specs](https://github.com/guard/listen/commit/1e457b13b1bb8a25d2240428ce5ed488bafbed1f).
287
288
  * [Travis Tilley (ttilley)][] for this awesome work on [fssm][] & [rb-fsevent][].
288
289
  * [Nathan Weizenbaum (nex3)][] for [rb-inotify][], a thorough inotify wrapper.
290
+ * [Mathieu Arnold (mat813)][] for [rb-kqueue][], a simple kqueue wrapper.
289
291
  * [stereobooster][] for [rb-fchange][], windows support wouldn't exist without him.
290
292
  * [Yehuda Katz (wycats)][] for [vigilo][], that has been a great source of inspiration.
291
293
 
@@ -304,6 +306,7 @@ For questions please join us in our [Google group](http://groups.google.com/grou
304
306
  [Travis Tilley (ttilley)]: https://github.com/ttilley
305
307
  [fssm]: https://github.com/ttilley/fssm
306
308
  [rb-fsevent]: https://github.com/thibaudgg/rb-fsevent
309
+ [Mathieu Arnold (mat813)]: https://github.com/mat813
307
310
  [Nathan Weizenbaum (nex3)]: https://github.com/nex3
308
311
  [rb-inotify]: https://github.com/nex3/rb-inotify
309
312
  [stereobooster]: https://github.com/stereobooster
@@ -1,14 +1,16 @@
1
1
  module Listen
2
2
 
3
- autoload :Turnstile, 'listen/turnstile'
4
- autoload :Listener, 'listen/listener'
5
- autoload :MultiListener, 'listen/multi_listener'
6
- autoload :DirectoryRecord, 'listen/directory_record'
7
- autoload :Adapter, 'listen/adapter'
3
+ autoload :Turnstile, 'listen/turnstile'
4
+ autoload :Listener, 'listen/listener'
5
+ autoload :MultiListener, 'listen/multi_listener'
6
+ autoload :DirectoryRecord, 'listen/directory_record'
7
+ autoload :DependencyManager, 'listen/dependency_manager'
8
+ autoload :Adapter, 'listen/adapter'
8
9
 
9
10
  module Adapters
10
11
  autoload :Darwin, 'listen/adapters/darwin'
11
12
  autoload :Linux, 'listen/adapters/linux'
13
+ autoload :BSD, 'listen/adapters/bsd'
12
14
  autoload :Windows, 'listen/adapters/windows'
13
15
  autoload :Polling, 'listen/adapters/polling'
14
16
  end
@@ -10,8 +10,15 @@ module Listen
10
10
  # The default delay between checking for changes.
11
11
  DEFAULT_LATENCY = 0.25
12
12
 
13
+ # The default warning message when there is a missing dependency.
14
+ MISSING_DEPENDENCY_MESSAGE = <<-EOS.gsub(/^\s*/, '')
15
+ For a better performance, it's recommended that you satisfy the missing dependency.
16
+ EOS
17
+
13
18
  # The default warning message when falling back to polling adapter.
14
- POLLING_FALLBACK_MESSAGE = "WARNING: Listen has fallen back to polling, learn more at https://github.com/guard/listen#fallback."
19
+ POLLING_FALLBACK_MESSAGE = <<-EOS.gsub(/^\s*/, '')
20
+ Listen will be polling changes. Learn more at https://github.com/guard/listen#polling-fallback.
21
+ EOS
15
22
 
16
23
  # Selects the appropriate adapter implementation for the
17
24
  # current OS and initializes it.
@@ -31,18 +38,28 @@ module Listen
31
38
  def self.select_and_initialize(directories, options = {}, &callback)
32
39
  return Adapters::Polling.new(directories, options, &callback) if options.delete(:force_polling)
33
40
 
34
- if Adapters::Darwin.usable_and_works?(directories, options)
35
- Adapters::Darwin.new(directories, options, &callback)
36
- elsif Adapters::Linux.usable_and_works?(directories, options)
37
- Adapters::Linux.new(directories, options, &callback)
38
- elsif Adapters::Windows.usable_and_works?(directories, options)
39
- Adapters::Windows.new(directories, options, &callback)
40
- else
41
- unless options[:polling_fallback_message] == false
42
- Kernel.warn(options[:polling_fallback_message] || POLLING_FALLBACK_MESSAGE)
41
+ warning = ''
42
+
43
+ begin
44
+ if Adapters::Darwin.usable_and_works?(directories, options)
45
+ return Adapters::Darwin.new(directories, options, &callback)
46
+ elsif Adapters::Linux.usable_and_works?(directories, options)
47
+ return Adapters::Linux.new(directories, options, &callback)
48
+ elsif Adapters::BSD.usable_and_works?(directories, options)
49
+ return Adapters::BSD.new(directories, options, &callback)
50
+ elsif Adapters::Windows.usable_and_works?(directories, options)
51
+ return Adapters::Windows.new(directories, options, &callback)
43
52
  end
44
- Adapters::Polling.new(directories, options, &callback)
53
+ rescue DependencyManager::Error => e
54
+ warning += e.message + "\n" + MISSING_DEPENDENCY_MESSAGE
55
+ end
56
+
57
+ unless options[:polling_fallback_message] == false
58
+ warning += options[:polling_fallback_message] || POLLING_FALLBACK_MESSAGE
59
+ Kernel.warn "[Listen warning]:\n" + warning.gsub(/^(.*)/, ' \1')
45
60
  end
61
+
62
+ Adapters::Polling.new(directories, options, &callback)
46
63
  end
47
64
 
48
65
  # Initializes the adapter.
@@ -50,6 +67,7 @@ module Listen
50
67
  # @param [String, Array<String>] directories the directories to watch
51
68
  # @param [Hash] options the adapter options
52
69
  # @option options [Float] latency the delay between checking for changes in seconds
70
+ # @option options [Boolean] report_changes whether or not to automatically report changes (run the callback)
53
71
  #
54
72
  # @yield [changed_dirs, options] callback Callback called when a change happens
55
73
  # @yieldparam [Array<String>] changed_dirs the changed directories
@@ -60,12 +78,13 @@ module Listen
60
78
  def initialize(directories, options = {}, &callback)
61
79
  @directories = Array(directories)
62
80
  @callback = callback
63
- @latency ||= DEFAULT_LATENCY
64
- @latency = options[:latency] if options[:latency]
65
81
  @paused = false
66
82
  @mutex = Mutex.new
67
83
  @changed_dirs = Set.new
68
84
  @turnstile = Turnstile.new
85
+ @latency ||= DEFAULT_LATENCY
86
+ @latency = options[:latency] if options[:latency]
87
+ @report_changes = options[:report_changes].nil? ? true : options[:report_changes]
69
88
  end
70
89
 
71
90
  # Starts the adapter.
@@ -92,12 +111,37 @@ module Listen
92
111
  end
93
112
 
94
113
  # Blocks the main thread until the poll thread
95
- # calls the callback.
114
+ # runs the callback.
96
115
  #
97
116
  def wait_for_callback
98
117
  @turnstile.wait unless @paused
99
118
  end
100
119
 
120
+ # Blocks the main thread until N changes are
121
+ # detected.
122
+ #
123
+ def wait_for_changes(goal = 0)
124
+ changes = 0
125
+
126
+ loop do
127
+ @mutex.synchronize { changes = @changed_dirs.size }
128
+
129
+ return if @paused || @stop
130
+ return if changes >= goal
131
+
132
+ sleep(@latency)
133
+ end
134
+ end
135
+
136
+ # Checks if the adapter is usable on the current OS.
137
+ #
138
+ # @return [Boolean] whether usable or not
139
+ #
140
+ def self.usable?
141
+ load_depenencies
142
+ dependencies_loaded?
143
+ end
144
+
101
145
  # Checks if the adapter is usable and works on the current OS.
102
146
  #
103
147
  # @param [String, Array<String>] directories the directories to watch
@@ -124,7 +168,7 @@ module Listen
124
168
  def self.works?(directory, options = {})
125
169
  work = false
126
170
  test_file = "#{directory}/.listen_test"
127
- callback = lambda { |changed_dirs, options| work = true }
171
+ callback = lambda { |*| work = true }
128
172
  adapter = self.new(directory, options, &callback)
129
173
  adapter.start(false)
130
174
 
@@ -140,27 +184,30 @@ module Listen
140
184
  adapter.stop if adapter && adapter.started?
141
185
  end
142
186
 
187
+ # Runs the callback and passes it the changes if there are any.
188
+ #
189
+ def report_changes
190
+ changed_dirs = nil
191
+
192
+ @mutex.synchronize do
193
+ return if @changed_dirs.empty?
194
+ changed_dirs = @changed_dirs.to_a
195
+ @changed_dirs.clear
196
+ end
197
+
198
+ @callback.call(changed_dirs, {})
199
+ @turnstile.signal
200
+ end
201
+
143
202
  private
144
203
 
145
204
  # Polls changed directories and reports them back
146
205
  # when there are changes.
147
206
  #
148
- # @option [Boolean] recursive whether or not to pass the recursive option to the callback
149
- #
150
- def poll_changed_dirs(recursive = false)
207
+ def poll_changed_dirs
151
208
  until @stop
152
209
  sleep(@latency)
153
- next if @changed_dirs.empty?
154
-
155
- changed_dirs = []
156
-
157
- @mutex.synchronize do
158
- changed_dirs = @changed_dirs.to_a
159
- @changed_dirs.clear
160
- end
161
-
162
- @callback.call(changed_dirs, recursive ? {:recursive => recursive} : {})
163
- @turnstile.signal
210
+ report_changes
164
211
  end
165
212
  end
166
213
  end
@@ -0,0 +1,112 @@
1
+ module Listen
2
+ module Adapters
3
+
4
+ # Listener implementation for BSD's `kqueue`.
5
+ #
6
+ class BSD < Adapter
7
+ extend DependencyManager
8
+
9
+ # Declare the adapter's dependencies
10
+ dependency 'rb-kqueue', '~> 0.2'
11
+
12
+ # Watched kqueue events
13
+ #
14
+ # @see http://www.freebsd.org/cgi/man.cgi?query=kqueue
15
+ # @see https://github.com/nex3/rb-kqueue/blob/master/lib/rb-kqueue/queue.rb
16
+ #
17
+ EVENTS = [ :delete, :write, :extend, :attrib, :link, :rename, :revoke ]
18
+
19
+ # Initializes the Adapter. See {Listen::Adapter#initialize} for
20
+ # more info.
21
+ #
22
+ def initialize(directories, options = {}, &callback)
23
+ super
24
+ @kqueue = init_kqueue
25
+ end
26
+
27
+ # Starts the adapter.
28
+ #
29
+ # @param [Boolean] blocking whether or not to block the current thread after starting
30
+ #
31
+ def start(blocking = true)
32
+ @mutex.synchronize do
33
+ return if @stop == false
34
+ super
35
+ end
36
+
37
+ @kqueue_thread = Thread.new do
38
+ until @stop
39
+ @kqueue.poll
40
+ sleep(@latency)
41
+ end
42
+ end
43
+ @poll_thread = Thread.new { poll_changed_dirs } if @report_changes
44
+
45
+ @kqueue_thread.join if blocking
46
+ end
47
+
48
+ # Stops the adapter.
49
+ #
50
+ def stop
51
+ @mutex.synchronize do
52
+ return if @stop == true
53
+ super
54
+ end
55
+
56
+ @kqueue.stop
57
+ Thread.kill(@kqueue_thread) if @kqueue_thread
58
+ @poll_thread.join if @poll_thread
59
+ end
60
+
61
+ # Checks if the adapter is usable on the current OS.
62
+ #
63
+ # @return [Boolean] whether usable or not
64
+ #
65
+ def self.usable?
66
+ return false unless RbConfig::CONFIG['target_os'] =~ /freebsd/i
67
+ super
68
+ end
69
+
70
+ private
71
+
72
+ # Initializes a kqueue Queue and adds a watcher for each files in
73
+ # the directories passed to the adapter.
74
+ #
75
+ # @return [INotify::Notifier] initialized kqueue
76
+ #
77
+ def init_kqueue
78
+ require 'find'
79
+
80
+ callback = lambda do |event|
81
+ path = event.watcher.path
82
+ @mutex.synchronize do
83
+ # kqueue watches everything, but Listen only needs the
84
+ # directory where stuffs happens.
85
+ @changed_dirs << (File.directory?(path) ? path : File.dirname(path))
86
+
87
+ # If it is a directory, and it has a write flag, it means a
88
+ # file has been added so find out which and deal with it.
89
+ # No need to check for removed file, kqueue will forget them
90
+ # when the vfs does..
91
+ if File.directory?(path) && !(event.flags & [:write]).empty?
92
+ queue = event.watcher.queue
93
+ Find.find(path) do |file|
94
+ unless queue.watchers.detect {|k,v| v.path == file.to_s}
95
+ queue.watch_file(file, *EVENTS, &callback)
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ KQueue::Queue.new.tap do |queue|
103
+ @directories.each do |directory|
104
+ Find.find(directory) do |path|
105
+ queue.watch_file(path, *EVENTS, &callback)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end