sass 3.1.0 → 3.3.0
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.
- checksums.yaml +7 -0
- data/CONTRIBUTING +1 -1
- data/MIT-LICENSE +2 -2
- data/README.md +29 -17
- data/Rakefile +43 -9
- data/VERSION +1 -1
- data/VERSION_DATE +1 -0
- data/VERSION_NAME +1 -1
- data/bin/sass +6 -1
- data/bin/sass-convert +6 -1
- data/bin/scss +6 -1
- data/ext/mkrf_conf.rb +27 -0
- data/lib/sass/cache_stores/base.rb +7 -3
- data/lib/sass/cache_stores/chain.rb +3 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -7
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +2 -1
- data/lib/sass/css.rb +168 -53
- data/lib/sass/engine.rb +502 -174
- data/lib/sass/environment.rb +151 -111
- data/lib/sass/error.rb +7 -7
- data/lib/sass/exec.rb +176 -60
- data/lib/sass/features.rb +40 -0
- data/lib/sass/importers/base.rb +46 -7
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +113 -30
- data/lib/sass/importers.rb +1 -0
- data/lib/sass/logger/base.rb +30 -0
- data/lib/sass/logger/log_level.rb +45 -0
- data/lib/sass/logger.rb +12 -0
- data/lib/sass/media.rb +213 -0
- data/lib/sass/plugin/compiler.rb +194 -104
- data/lib/sass/plugin/configuration.rb +18 -25
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +37 -11
- data/lib/sass/plugin.rb +10 -13
- data/lib/sass/railtie.rb +2 -1
- data/lib/sass/repl.rb +5 -6
- data/lib/sass/script/css_lexer.rb +8 -4
- data/lib/sass/script/css_parser.rb +5 -2
- data/lib/sass/script/functions.rb +1547 -618
- data/lib/sass/script/lexer.rb +122 -72
- data/lib/sass/script/parser.rb +304 -135
- data/lib/sass/script/tree/funcall.rb +306 -0
- data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
- data/lib/sass/script/tree/list_literal.rb +77 -0
- data/lib/sass/script/tree/literal.rb +45 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
- data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
- data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
- data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +15 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +238 -0
- data/lib/sass/script/value/bool.rb +40 -0
- data/lib/sass/script/{color.rb → value/color.rb} +256 -74
- data/lib/sass/script/value/deprecated_false.rb +55 -0
- data/lib/sass/script/value/helpers.rb +155 -0
- data/lib/sass/script/value/list.rb +128 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +49 -0
- data/lib/sass/script/{number.rb → value/number.rb} +115 -62
- data/lib/sass/script/{string.rb → value/string.rb} +9 -11
- data/lib/sass/script/value.rb +12 -0
- data/lib/sass/script.rb +35 -9
- data/lib/sass/scss/css_parser.rb +2 -12
- data/lib/sass/scss/parser.rb +657 -230
- data/lib/sass/scss/rx.rb +17 -12
- data/lib/sass/scss/static_parser.rb +37 -6
- data/lib/sass/scss.rb +0 -1
- data/lib/sass/selector/abstract_sequence.rb +35 -3
- data/lib/sass/selector/comma_sequence.rb +29 -14
- data/lib/sass/selector/sequence.rb +371 -74
- data/lib/sass/selector/simple.rb +28 -13
- data/lib/sass/selector/simple_sequence.rb +163 -36
- data/lib/sass/selector.rb +138 -36
- data/lib/sass/shared.rb +3 -5
- data/lib/sass/source/map.rb +196 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +126 -0
- data/lib/sass/supports.rb +228 -0
- data/lib/sass/tree/at_root_node.rb +82 -0
- data/lib/sass/tree/comment_node.rb +34 -29
- data/lib/sass/tree/content_node.rb +9 -0
- data/lib/sass/tree/css_import_node.rb +60 -0
- data/lib/sass/tree/debug_node.rb +3 -3
- data/lib/sass/tree/directive_node.rb +33 -3
- data/lib/sass/tree/each_node.rb +9 -9
- data/lib/sass/tree/extend_node.rb +20 -6
- data/lib/sass/tree/for_node.rb +6 -6
- data/lib/sass/tree/function_node.rb +12 -4
- data/lib/sass/tree/if_node.rb +2 -15
- data/lib/sass/tree/import_node.rb +11 -5
- data/lib/sass/tree/media_node.rb +27 -11
- data/lib/sass/tree/mixin_def_node.rb +15 -4
- data/lib/sass/tree/mixin_node.rb +27 -7
- data/lib/sass/tree/node.rb +69 -35
- data/lib/sass/tree/prop_node.rb +47 -31
- data/lib/sass/tree/return_node.rb +4 -3
- data/lib/sass/tree/root_node.rb +20 -4
- data/lib/sass/tree/rule_node.rb +37 -26
- data/lib/sass/tree/supports_node.rb +38 -0
- data/lib/sass/tree/trace_node.rb +33 -0
- data/lib/sass/tree/variable_node.rb +10 -4
- data/lib/sass/tree/visitors/base.rb +5 -8
- data/lib/sass/tree/visitors/check_nesting.rb +67 -52
- data/lib/sass/tree/visitors/convert.rb +134 -53
- data/lib/sass/tree/visitors/cssize.rb +245 -51
- data/lib/sass/tree/visitors/deep_copy.rb +102 -0
- data/lib/sass/tree/visitors/extend.rb +68 -0
- data/lib/sass/tree/visitors/perform.rb +331 -105
- data/lib/sass/tree/visitors/set_options.rb +125 -0
- data/lib/sass/tree/visitors/to_css.rb +259 -95
- data/lib/sass/tree/warn_node.rb +3 -3
- data/lib/sass/tree/while_node.rb +3 -3
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/multibyte_string_scanner.rb +157 -0
- data/lib/sass/util/normalized_map.rb +130 -0
- data/lib/sass/util/ordered_hash.rb +192 -0
- data/lib/sass/util/subset_map.rb +11 -2
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +565 -39
- data/lib/sass/version.rb +27 -15
- data/lib/sass.rb +39 -4
- data/test/sass/cache_test.rb +15 -0
- data/test/sass/compiler_test.rb +223 -0
- data/test/sass/conversion_test.rb +901 -107
- data/test/sass/css2sass_test.rb +94 -0
- data/test/sass/engine_test.rb +1059 -164
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +933 -837
- data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
- data/test/sass/functions_test.rb +995 -136
- data/test/sass/importer_test.rb +338 -18
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/more_results/more_import.css +2 -2
- data/test/sass/plugin_test.rb +114 -30
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/import.css +2 -2
- data/test/sass/results/import_charset.css +1 -0
- data/test/sass/results/import_charset_1_8.css +1 -0
- data/test/sass/results/import_charset_ibm866.css +1 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/script.css +1 -1
- data/test/sass/results/scss_import.css +2 -2
- data/test/sass/results/units.css +2 -2
- data/test/sass/script_conversion_test.rb +43 -1
- data/test/sass/script_test.rb +380 -36
- data/test/sass/scss/css_test.rb +257 -75
- data/test/sass/scss/scss_test.rb +2322 -110
- data/test/sass/source_map_test.rb +887 -0
- data/test/sass/templates/_cached_import_option_partial.scss +1 -0
- data/test/sass/templates/_double_import_loop2.sass +1 -0
- data/test/sass/templates/_filename_fn_import.scss +11 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/import_charset.sass +2 -0
- data/test/sass/templates/import_charset_1_8.sass +2 -0
- data/test/sass/templates/import_charset_ibm866.sass +2 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/same_name_different_ext.sass +2 -0
- data/test/sass/templates/same_name_different_ext.scss +1 -0
- data/test/sass/templates/same_name_different_partiality.scss +1 -0
- data/test/sass/templates/single_import_loop.sass +1 -0
- data/test/sass/templates/subdir/import_up1.scss +1 -0
- data/test/sass/templates/subdir/import_up2.scss +1 -0
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/normalized_map_test.rb +51 -0
- data/test/sass/util_test.rb +183 -0
- data/test/sass/value_helpers_test.rb +181 -0
- data/test/test_helper.rb +45 -5
- data/vendor/listen/CHANGELOG.md +228 -0
- data/vendor/listen/CONTRIBUTING.md +38 -0
- data/vendor/listen/Gemfile +30 -0
- data/vendor/listen/Guardfile +8 -0
- data/vendor/{fssm → listen}/LICENSE +1 -1
- data/vendor/listen/README.md +315 -0
- data/vendor/listen/Rakefile +47 -0
- data/vendor/listen/Vagrantfile +96 -0
- data/vendor/listen/lib/listen/adapter.rb +214 -0
- data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
- data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
- data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
- data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
- data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
- data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
- data/vendor/listen/lib/listen/directory_record.rb +371 -0
- data/vendor/listen/lib/listen/listener.rb +225 -0
- data/vendor/listen/lib/listen/multi_listener.rb +143 -0
- data/vendor/listen/lib/listen/turnstile.rb +28 -0
- data/vendor/listen/lib/listen/version.rb +3 -0
- data/vendor/listen/lib/listen.rb +40 -0
- data/vendor/listen/listen.gemspec +22 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
- data/vendor/listen/spec/listen/listener_spec.rb +169 -0
- data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
- data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
- data/vendor/listen/spec/listen_spec.rb +73 -0
- data/vendor/listen/spec/spec_helper.rb +21 -0
- data/vendor/listen/spec/support/adapter_helper.rb +629 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
- data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
- data/vendor/listen/spec/support/listeners_helper.rb +156 -0
- data/vendor/listen/spec/support/platform_helper.rb +15 -0
- metadata +344 -271
- data/lib/sass/less.rb +0 -382
- data/lib/sass/script/bool.rb +0 -18
- data/lib/sass/script/funcall.rb +0 -162
- data/lib/sass/script/list.rb +0 -76
- data/lib/sass/script/literal.rb +0 -245
- data/lib/sass/script/variable.rb +0 -54
- data/lib/sass/scss/sass_parser.rb +0 -11
- data/test/sass/less_conversion_test.rb +0 -653
- data/vendor/fssm/README.markdown +0 -55
- data/vendor/fssm/Rakefile +0 -59
- data/vendor/fssm/VERSION.yml +0 -5
- data/vendor/fssm/example.rb +0 -9
- data/vendor/fssm/fssm.gemspec +0 -77
- data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
- data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
- data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
- data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
- data/vendor/fssm/lib/fssm/monitor.rb +0 -26
- data/vendor/fssm/lib/fssm/path.rb +0 -91
- data/vendor/fssm/lib/fssm/pathname.rb +0 -502
- data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
- data/vendor/fssm/lib/fssm/state/file.rb +0 -24
- data/vendor/fssm/lib/fssm/support.rb +0 -63
- data/vendor/fssm/lib/fssm/tree.rb +0 -176
- data/vendor/fssm/lib/fssm.rb +0 -33
- data/vendor/fssm/profile/prof-cache.rb +0 -40
- data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
- data/vendor/fssm/profile/prof-pathname.rb +0 -68
- data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
- data/vendor/fssm/profile/prof.html +0 -2379
- data/vendor/fssm/spec/path_spec.rb +0 -75
- data/vendor/fssm/spec/root/duck/quack.txt +0 -0
- data/vendor/fssm/spec/root/file.css +0 -0
- data/vendor/fssm/spec/root/file.rb +0 -0
- data/vendor/fssm/spec/root/file.yml +0 -0
- data/vendor/fssm/spec/root/moo/cow.txt +0 -0
- data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -0,0 +1,143 @@
|
|
1
|
+
module Listen
|
2
|
+
class MultiListener < Listener
|
3
|
+
attr_reader :directories, :directories_records, :adapter
|
4
|
+
|
5
|
+
# Initializes the multiple directories listener.
|
6
|
+
#
|
7
|
+
# @param [String] directories the directories to listen to
|
8
|
+
# @param [Hash] options the listen options
|
9
|
+
# @option options [Regexp] ignore a pattern for ignoring paths
|
10
|
+
# @option options [Regexp] filter a pattern for filtering paths
|
11
|
+
# @option options [Float] latency the delay between checking for changes in seconds
|
12
|
+
# @option options [Boolean] force_polling whether to force the polling adapter or not
|
13
|
+
# @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
|
14
|
+
#
|
15
|
+
# @yield [modified, added, removed] the changed files
|
16
|
+
# @yieldparam [Array<String>] modified the list of modified files
|
17
|
+
# @yieldparam [Array<String>] added the list of added files
|
18
|
+
# @yieldparam [Array<String>] removed the list of removed files
|
19
|
+
#
|
20
|
+
def initialize(*args, &block)
|
21
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
22
|
+
directories = args
|
23
|
+
|
24
|
+
@block = block
|
25
|
+
@directories = directories.map { |d| Pathname.new(d).realpath.to_s }
|
26
|
+
@directories_records = @directories.map { |d| DirectoryRecord.new(d) }
|
27
|
+
|
28
|
+
ignore(*options.delete(:ignore)) if options[:ignore]
|
29
|
+
filter(*options.delete(:filter)) if options[:filter]
|
30
|
+
|
31
|
+
@adapter_options = options
|
32
|
+
end
|
33
|
+
|
34
|
+
# Starts the listener by initializing the adapter and building
|
35
|
+
# the directory record concurrently, then it starts the adapter to watch
|
36
|
+
# for changes.
|
37
|
+
#
|
38
|
+
# @param [Boolean] blocking whether or not to block the current thread after starting
|
39
|
+
#
|
40
|
+
def start(blocking = true)
|
41
|
+
t = Thread.new { @directories_records.each { |r| r.build } }
|
42
|
+
@adapter = initialize_adapter
|
43
|
+
t.join
|
44
|
+
@adapter.start(blocking)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Unpauses the listener.
|
48
|
+
#
|
49
|
+
# @return [Listen::Listener] the listener
|
50
|
+
#
|
51
|
+
def unpause
|
52
|
+
@directories_records.each { |r| r.build }
|
53
|
+
@adapter.paused = false
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
# Adds ignored paths to the listener.
|
58
|
+
#
|
59
|
+
# @param (see Listen::DirectoryRecord#ignore)
|
60
|
+
#
|
61
|
+
# @return [Listen::Listener] the listener
|
62
|
+
#
|
63
|
+
def ignore(*paths)
|
64
|
+
@directories_records.each { |r| r.ignore(*paths) }
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# Replaces ignored paths in the listener.
|
69
|
+
#
|
70
|
+
# @param (see Listen::DirectoryRecord#ignore!)
|
71
|
+
#
|
72
|
+
# @return [Listen::Listener] the listener
|
73
|
+
#
|
74
|
+
def ignore!(*paths)
|
75
|
+
@directories_records.each { |r| r.ignore!(*paths) }
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
# Adds file filters to the listener.
|
80
|
+
#
|
81
|
+
# @param (see Listen::DirectoryRecord#filter)
|
82
|
+
#
|
83
|
+
# @return [Listen::Listener] the listener
|
84
|
+
#
|
85
|
+
def filter(*regexps)
|
86
|
+
@directories_records.each { |r| r.filter(*regexps) }
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
# Replaces file filters in the listener.
|
91
|
+
#
|
92
|
+
# @param (see Listen::DirectoryRecord#filter!)
|
93
|
+
#
|
94
|
+
# @return [Listen::Listener] the listener
|
95
|
+
#
|
96
|
+
def filter!(*regexps)
|
97
|
+
@directories_records.each { |r| r.filter!(*regexps) }
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
# Runs the callback passing it the changes if there are any.
|
102
|
+
#
|
103
|
+
# @param (see Listen::DirectoryRecord#fetch_changes)
|
104
|
+
#
|
105
|
+
def on_change(directories_to_search, options = {})
|
106
|
+
changes = fetch_records_changes(directories_to_search, options)
|
107
|
+
unless changes.values.all? { |paths| paths.empty? }
|
108
|
+
@block.call(changes[:modified],changes[:added],changes[:removed])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# Initializes an adapter passing it the callback and adapters' options.
|
115
|
+
#
|
116
|
+
def initialize_adapter
|
117
|
+
callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
|
118
|
+
Adapter.select_and_initialize(@directories, @adapter_options, &callback)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Returns the sum of all the changes to the directories records
|
122
|
+
#
|
123
|
+
# @param (see Listen::DirectoryRecord#fetch_changes)
|
124
|
+
#
|
125
|
+
# @return [Hash] the changes
|
126
|
+
#
|
127
|
+
def fetch_records_changes(directories_to_search, options)
|
128
|
+
@directories_records.inject({}) do |h, r|
|
129
|
+
# directory records skips paths outside their range, so passing the
|
130
|
+
# whole `directories` array is not a problem.
|
131
|
+
record_changes = r.fetch_changes(directories_to_search, options.merge(:relative_paths => DEFAULT_TO_RELATIVE_PATHS))
|
132
|
+
|
133
|
+
if h.empty?
|
134
|
+
h.merge!(record_changes)
|
135
|
+
else
|
136
|
+
h.each { |k, v| h[k] += record_changes[k] }
|
137
|
+
end
|
138
|
+
|
139
|
+
h
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Listen
|
2
|
+
# Allows two threads to wait on eachother.
|
3
|
+
#
|
4
|
+
# @note Only two threads can be used with this Turnstile
|
5
|
+
# because of the current implementation.
|
6
|
+
class Turnstile
|
7
|
+
|
8
|
+
# Initialize the turnstile.
|
9
|
+
#
|
10
|
+
def initialize
|
11
|
+
# Until ruby offers semahpores, only queues can be used
|
12
|
+
# to implement a turnstile.
|
13
|
+
@q = Queue.new
|
14
|
+
end
|
15
|
+
|
16
|
+
# Blocks the current thread until a signal is received.
|
17
|
+
#
|
18
|
+
def wait
|
19
|
+
@q.pop if @q.num_waiting == 0
|
20
|
+
end
|
21
|
+
|
22
|
+
# Unblocks the waiting thread if there is one.
|
23
|
+
#
|
24
|
+
def signal
|
25
|
+
@q.push :dummy if @q.num_waiting == 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Listen
|
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 :DependencyManager, 'listen/dependency_manager'
|
8
|
+
autoload :Adapter, 'listen/adapter'
|
9
|
+
|
10
|
+
module Adapters
|
11
|
+
autoload :Darwin, 'listen/adapters/darwin'
|
12
|
+
autoload :Linux, 'listen/adapters/linux'
|
13
|
+
autoload :BSD, 'listen/adapters/bsd'
|
14
|
+
autoload :Windows, 'listen/adapters/windows'
|
15
|
+
autoload :Polling, 'listen/adapters/polling'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Listens to filesystem modifications on a either single directory or multiple directories.
|
19
|
+
#
|
20
|
+
# @param (see Listen::Listener#new)
|
21
|
+
# @param (see Listen::MultiListener#new)
|
22
|
+
#
|
23
|
+
# @yield [modified, added, removed] the changed files
|
24
|
+
# @yieldparam [Array<String>] modified the list of modified files
|
25
|
+
# @yieldparam [Array<String>] added the list of added files
|
26
|
+
# @yieldparam [Array<String>] removed the list of removed files
|
27
|
+
#
|
28
|
+
# @return [Listen::Listener] the file listener if no block given
|
29
|
+
#
|
30
|
+
def self.to(*args, &block)
|
31
|
+
listener = if args.length == 1 || ! args[1].is_a?(String)
|
32
|
+
Listener.new(*args, &block)
|
33
|
+
else
|
34
|
+
MultiListener.new(*args, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
block ? listener.start : listener
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'listen/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'listen'
|
7
|
+
s.version = Listen::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ['Thibaud Guillaume-Gentil', 'Maher Sallam']
|
10
|
+
s.email = ['thibaud@thibaud.me', 'maher@sallam.me']
|
11
|
+
s.homepage = 'https://github.com/guard/listen'
|
12
|
+
s.summary = 'Listen to file modifications'
|
13
|
+
s.description = 'The Listen gem listens to file modifications and notifies you about the changes. Works everywhere!'
|
14
|
+
|
15
|
+
s.required_rubygems_version = '>= 1.3.6'
|
16
|
+
s.rubyforge_project = 'listen'
|
17
|
+
|
18
|
+
s.add_development_dependency 'bundler'
|
19
|
+
|
20
|
+
s.files = Dir.glob('{lib}/**/*') + %w[CHANGELOG.md LICENSE README.md]
|
21
|
+
s.require_path = 'lib'
|
22
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen::Adapter do
|
4
|
+
subject { described_class.new('dir') }
|
5
|
+
|
6
|
+
describe '#initialize' do
|
7
|
+
it 'sets the latency to the default one' do
|
8
|
+
subject.latency.should eq described_class::DEFAULT_LATENCY
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'accepts a single directory to watch' do
|
12
|
+
described_class.new('dir').directories = %w{dir}
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'accepts multiple directories to watch' do
|
16
|
+
described_class.new(%w{dir1 dir2}).directories.should eq %w{dir1 dir2}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".select_and_initialize" do
|
21
|
+
before do
|
22
|
+
Listen::Adapters::Darwin.stub(:usable_and_works?) { false }
|
23
|
+
Listen::Adapters::Linux.stub(:usable_and_works?) { false }
|
24
|
+
Listen::Adapters::BSD.stub(:usable_and_works?) { false }
|
25
|
+
Listen::Adapters::Windows.stub(:usable_and_works?) { false }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with no specific adapter usable" do
|
29
|
+
it "returns Listen::Adapters::Polling instance" do
|
30
|
+
Kernel.stub(:warn)
|
31
|
+
Listen::Adapters::Polling.should_receive(:new).with('dir', {})
|
32
|
+
described_class.select_and_initialize('dir')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'warns with the default polling fallback message' do
|
36
|
+
Kernel.should_receive(:warn).with(/#{Listen::Adapter::POLLING_FALLBACK_MESSAGE}/)
|
37
|
+
described_class.select_and_initialize('dir')
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when the dependencies of an adapter are not satisfied' do
|
41
|
+
before do
|
42
|
+
Listen::Adapters::Darwin.stub(:usable_and_works?).and_raise(Listen::DependencyManager::Error)
|
43
|
+
Listen::Adapters::Linux.stub(:usable_and_works?).and_raise(Listen::DependencyManager::Error)
|
44
|
+
Listen::Adapters::BSD.stub(:usable_and_works?).and_raise(Listen::DependencyManager::Error)
|
45
|
+
Listen::Adapters::Windows.stub(:usable_and_works?).and_raise(Listen::DependencyManager::Error)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'invites the user to satisfy the dependencies of the adapter in the warning' do
|
49
|
+
Kernel.should_receive(:warn).with(/#{Listen::Adapter::MISSING_DEPENDENCY_MESSAGE}/)
|
50
|
+
described_class.select_and_initialize('dir')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "with custom polling_fallback_message option" do
|
55
|
+
it "warns with the custom polling fallback message" do
|
56
|
+
Kernel.should_receive(:warn).with(/custom/)
|
57
|
+
described_class.select_and_initialize('dir', :polling_fallback_message => 'custom')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "with polling_fallback_message to false" do
|
62
|
+
it "doesn't warn with a polling fallback message" do
|
63
|
+
Kernel.should_not_receive(:warn)
|
64
|
+
described_class.select_and_initialize('dir', :polling_fallback_message => false)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "on Mac OX >= 10.6" do
|
70
|
+
before { Listen::Adapters::Darwin.stub(:usable_and_works?) { true } }
|
71
|
+
|
72
|
+
it "uses Listen::Adapters::Darwin" do
|
73
|
+
Listen::Adapters::Darwin.should_receive(:new).with('dir', {})
|
74
|
+
described_class.select_and_initialize('dir')
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'when the use of the polling adapter is forced' do
|
78
|
+
it 'uses Listen::Adapters::Polling' do
|
79
|
+
Listen::Adapters::Polling.should_receive(:new).with('dir', {})
|
80
|
+
described_class.select_and_initialize('dir', :force_polling => true)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "on Linux" do
|
86
|
+
before { Listen::Adapters::Linux.stub(:usable_and_works?) { true } }
|
87
|
+
|
88
|
+
it "uses Listen::Adapters::Linux" do
|
89
|
+
Listen::Adapters::Linux.should_receive(:new).with('dir', {})
|
90
|
+
described_class.select_and_initialize('dir')
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when the use of the polling adapter is forced' do
|
94
|
+
it 'uses Listen::Adapters::Polling' do
|
95
|
+
Listen::Adapters::Polling.should_receive(:new).with('dir', {})
|
96
|
+
described_class.select_and_initialize('dir', :force_polling => true)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "on BSD" do
|
102
|
+
before { Listen::Adapters::BSD.stub(:usable_and_works?) { true } }
|
103
|
+
|
104
|
+
it "uses Listen::Adapters::BSD" do
|
105
|
+
Listen::Adapters::BSD.should_receive(:new).with('dir', {})
|
106
|
+
described_class.select_and_initialize('dir')
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'when the use of the polling adapter is forced' do
|
110
|
+
it 'uses Listen::Adapters::Polling' do
|
111
|
+
Listen::Adapters::Polling.should_receive(:new).with('dir', {})
|
112
|
+
described_class.select_and_initialize('dir', :force_polling => true)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "on Windows" do
|
118
|
+
before { Listen::Adapters::Windows.stub(:usable_and_works?) { true } }
|
119
|
+
|
120
|
+
it "uses Listen::Adapters::Windows" do
|
121
|
+
Listen::Adapters::Windows.should_receive(:new).with('dir', {})
|
122
|
+
described_class.select_and_initialize('dir')
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'when the use of the polling adapter is forced' do
|
126
|
+
it 'uses Listen::Adapters::Polling' do
|
127
|
+
Listen::Adapters::Polling.should_receive(:new).with('dir', {})
|
128
|
+
described_class.select_and_initialize('dir', :force_polling => true)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
[Listen::Adapters::Darwin, Listen::Adapters::Linux,
|
135
|
+
Listen::Adapters::BSD, Listen::Adapters::Windows].each do
|
136
|
+
|adapter_class|
|
137
|
+
if adapter_class.usable?
|
138
|
+
describe '.usable?' do
|
139
|
+
it 'checks the dependencies' do
|
140
|
+
adapter_class.should_receive(:load_depenencies)
|
141
|
+
adapter_class.should_receive(:dependencies_loaded?)
|
142
|
+
adapter_class.usable?
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe '.usable_and_works?' do
|
147
|
+
it 'checks if the adapter is usable' do
|
148
|
+
adapter_class.stub(:works?)
|
149
|
+
adapter_class.should_receive(:usable?)
|
150
|
+
adapter_class.usable_and_works?('dir')
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'with one directory' do
|
154
|
+
it 'tests if that directory actually work' do
|
155
|
+
fixtures do |path|
|
156
|
+
adapter_class.should_receive(:works?).with(path, anything).and_return(true)
|
157
|
+
adapter_class.usable_and_works?(path)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'with multiple directories' do
|
163
|
+
it 'tests if each directory passed does actually work' do
|
164
|
+
fixtures(3) do |path1, path2, path3|
|
165
|
+
adapter_class.should_receive(:works?).exactly(3).times.with do |path, options|
|
166
|
+
[path1, path2, path3].include? path
|
167
|
+
end.and_return(true)
|
168
|
+
adapter_class.usable_and_works?([path1, path2, path3])
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe '.works?' do
|
175
|
+
it 'does work' do
|
176
|
+
fixtures do |path|
|
177
|
+
adapter_class.works?(path).should be_true
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen::Adapters::BSD do
|
4
|
+
if bsd?
|
5
|
+
if Listen::Adapters::BSD.usable?
|
6
|
+
it "is usable on BSD" do
|
7
|
+
described_class.should be_usable
|
8
|
+
end
|
9
|
+
|
10
|
+
it_should_behave_like 'a filesystem adapter'
|
11
|
+
it_should_behave_like 'an adapter that call properly listener#on_change'
|
12
|
+
else
|
13
|
+
it "isn't usable on BSD with #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}" do
|
14
|
+
described_class.should_not be_usable
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
if linux?
|
20
|
+
it "isn't usable on Linux" do
|
21
|
+
described_class.should_not be_usable
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
if mac?
|
26
|
+
it "isn't usable on Mac OS X" do
|
27
|
+
described_class.should_not be_usable
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
if windows?
|
32
|
+
it "isn't usable on Windows" do
|
33
|
+
described_class.should_not be_usable
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen::Adapters::Darwin do
|
4
|
+
if mac?
|
5
|
+
if Listen::Adapters::Darwin.usable?
|
6
|
+
it "is usable on Mac OS X >= 10.6" do
|
7
|
+
described_class.should be_usable
|
8
|
+
end
|
9
|
+
|
10
|
+
it_should_behave_like 'a filesystem adapter'
|
11
|
+
it_should_behave_like 'an adapter that call properly listener#on_change'
|
12
|
+
else
|
13
|
+
it "isn't usable on Mac OS X with #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}" do
|
14
|
+
described_class.should_not be_usable
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
if windows?
|
21
|
+
it "isn't usable on Windows" do
|
22
|
+
described_class.should_not be_usable
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if linux?
|
27
|
+
it "isn't usable on Linux" do
|
28
|
+
described_class.should_not be_usable
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if bsd?
|
33
|
+
it "isn't usable on BSD" do
|
34
|
+
described_class.should_not be_usable
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen::Adapters::Linux do
|
4
|
+
if linux?
|
5
|
+
if Listen::Adapters::Linux.usable?
|
6
|
+
it "is usable on Linux" do
|
7
|
+
described_class.should be_usable
|
8
|
+
end
|
9
|
+
|
10
|
+
it_should_behave_like 'a filesystem adapter'
|
11
|
+
it_should_behave_like 'an adapter that call properly listener#on_change'
|
12
|
+
|
13
|
+
describe '#initialize' do
|
14
|
+
context 'when the inotify limit for watched files is not enough' do
|
15
|
+
before { INotify::Notifier.any_instance.should_receive(:watch).and_raise(Errno::ENOSPC) }
|
16
|
+
|
17
|
+
it 'fails gracefully' do
|
18
|
+
described_class.any_instance.should_receive(:abort).with(described_class::INOTIFY_LIMIT_MESSAGE)
|
19
|
+
described_class.new(File.dirname(__FILE__))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
else
|
24
|
+
it "isn't usable on Linux with #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}" do
|
25
|
+
described_class.should_not be_usable
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
if bsd?
|
31
|
+
it "isn't usable on BSD" do
|
32
|
+
described_class.should_not be_usable
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
if mac?
|
37
|
+
it "isn't usable on Mac OS X" do
|
38
|
+
described_class.should_not be_usable
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if windows?
|
43
|
+
it "isn't usable on Windows" do
|
44
|
+
described_class.should_not be_usable
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen::Adapters::Polling do
|
4
|
+
subject { described_class.new('dir') }
|
5
|
+
|
6
|
+
it_should_behave_like 'a filesystem adapter'
|
7
|
+
|
8
|
+
describe '#initialize' do
|
9
|
+
it 'sets the latency to the default polling one' do
|
10
|
+
subject.latency.should eq Listen::Adapters::DEFAULT_POLLING_LATENCY
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#poll' do
|
15
|
+
let(:listener) { mock(Listen::Listener) }
|
16
|
+
let(:callback) { lambda { |changed_dirs, options| @called = true; listener.on_change(changed_dirs, options) } }
|
17
|
+
|
18
|
+
after { subject.stop }
|
19
|
+
|
20
|
+
context 'with one directory to watch' do
|
21
|
+
subject { Listen::Adapters::Polling.new('dir', {}, &callback) }
|
22
|
+
|
23
|
+
it 'calls listener.on_change' do
|
24
|
+
listener.should_receive(:on_change).at_least(1).times.with(['dir'], :recursive => true)
|
25
|
+
subject.start(false)
|
26
|
+
subject.wait_for_callback
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'calls listener.on_change continuously' do
|
30
|
+
subject.latency = 0.001
|
31
|
+
listener.should_receive(:on_change).at_least(10).times.with(['dir'], :recursive => true)
|
32
|
+
subject.start(false)
|
33
|
+
10.times { subject.wait_for_callback }
|
34
|
+
end
|
35
|
+
|
36
|
+
it "doesn't call listener.on_change if paused" do
|
37
|
+
subject.paused = true
|
38
|
+
subject.start(false)
|
39
|
+
subject.wait_for_callback
|
40
|
+
@called.should be_nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'with multiple directories to watch' do
|
45
|
+
subject { Listen::Adapters::Polling.new(%w{dir1 dir2}, {}, &callback) }
|
46
|
+
|
47
|
+
it 'calls listener.on_change' do
|
48
|
+
listener.should_receive(:on_change).at_least(1).times.with(%w{dir1 dir2}, :recursive => true)
|
49
|
+
subject.start(false)
|
50
|
+
subject.wait_for_callback
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'calls listener.on_change continuously' do
|
54
|
+
subject.latency = 0.001
|
55
|
+
listener.should_receive(:on_change).at_least(10).times.with(%w{dir1 dir2}, :recursive => true)
|
56
|
+
subject.start(false)
|
57
|
+
10.times { subject.wait_for_callback }
|
58
|
+
end
|
59
|
+
|
60
|
+
it "doesn't call listener.on_change if paused" do
|
61
|
+
subject.paused = true
|
62
|
+
subject.start(false)
|
63
|
+
subject.wait_for_callback
|
64
|
+
@called.should be_nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen::Adapters::Windows do
|
4
|
+
if windows? && Listen::Adapters::Windows.usable?
|
5
|
+
it "is usable on Windows" do
|
6
|
+
described_class.should be_usable
|
7
|
+
end
|
8
|
+
|
9
|
+
it_should_behave_like 'a filesystem adapter'
|
10
|
+
it_should_behave_like 'an adapter that call properly listener#on_change'
|
11
|
+
end
|
12
|
+
|
13
|
+
if mac?
|
14
|
+
it "isn't usable on Mac OS X" do
|
15
|
+
described_class.should_not be_usable
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
if bsd?
|
20
|
+
it "isn't usable on BSD" do
|
21
|
+
described_class.should_not be_usable
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
if linux?
|
26
|
+
it "isn't usable on Linux" do
|
27
|
+
described_class.should_not be_usable
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|