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,629 @@
|
|
1
|
+
# Adapter watch
|
2
|
+
#
|
3
|
+
# @param [Listen::Listener] listener the adapter listener
|
4
|
+
# @param [String] path the path to watch
|
5
|
+
#
|
6
|
+
def watch(listener, expected_changes, *paths)
|
7
|
+
callback = lambda { |changed_dirs, options| @called = true; listener.on_change(changed_dirs) }
|
8
|
+
@adapter = Listen::Adapter.select_and_initialize(paths, { :report_changes => false, :latency => test_latency }, &callback)
|
9
|
+
|
10
|
+
forced_stop = false
|
11
|
+
prevent_deadlock = Proc.new { sleep(10); puts "Forcing stop"; @adapter.stop; forced_stop = true }
|
12
|
+
|
13
|
+
@adapter.start(false)
|
14
|
+
|
15
|
+
yield
|
16
|
+
|
17
|
+
t = Thread.new(&prevent_deadlock)
|
18
|
+
@adapter.wait_for_changes(expected_changes)
|
19
|
+
|
20
|
+
unless forced_stop
|
21
|
+
Thread.kill(t)
|
22
|
+
@adapter.report_changes
|
23
|
+
end
|
24
|
+
ensure
|
25
|
+
unless forced_stop
|
26
|
+
Thread.kill(t) if t
|
27
|
+
@adapter.stop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
shared_examples_for 'a filesystem adapter' do
|
32
|
+
subject { described_class.new(File.dirname(__FILE__), &Proc.new {}) }
|
33
|
+
|
34
|
+
describe '#start' do
|
35
|
+
after { subject.stop }
|
36
|
+
|
37
|
+
context 'with the blocking param set to true' do
|
38
|
+
it 'blocks the current thread after starting the workers' do
|
39
|
+
@called = false
|
40
|
+
t = Thread.new { subject.start(true); @called = true }
|
41
|
+
sleep(test_latency * 3)
|
42
|
+
Thread.kill(t) if t
|
43
|
+
@called.should be_false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with the blocking param set to false' do
|
48
|
+
it 'does not block the current thread after starting the workers' do
|
49
|
+
@called = false
|
50
|
+
t = Thread.new { subject.start(false); @called = true }
|
51
|
+
sleep(test_latency * 3)
|
52
|
+
Thread.kill(t) if t
|
53
|
+
@called.should be_true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#started?' do
|
59
|
+
context 'with a new adapter' do
|
60
|
+
it 'returns false' do
|
61
|
+
subject.should_not be_started
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with a stopped adapter' do
|
66
|
+
before { subject.start(false); subject.stop }
|
67
|
+
|
68
|
+
it 'returns false' do
|
69
|
+
subject.should_not be_started
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'with a started adapter' do
|
74
|
+
before { subject.start(false) }
|
75
|
+
after { subject.stop }
|
76
|
+
|
77
|
+
it 'returns true' do
|
78
|
+
subject.should be_started
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
shared_examples_for 'an adapter that call properly listener#on_change' do |*args|
|
85
|
+
options = (args.first && args.first.is_a?(Hash)) ? args.first : {}
|
86
|
+
let(:listener) { mock(Listen::Listener) }
|
87
|
+
before { described_class.stub(:works?) { true } }
|
88
|
+
|
89
|
+
context 'single file operations' do
|
90
|
+
context 'when a file is created' do
|
91
|
+
it 'detects the added file' do
|
92
|
+
fixtures do |path|
|
93
|
+
listener.should_receive(:on_change).once.with do |array|
|
94
|
+
array.should include(path)
|
95
|
+
end
|
96
|
+
|
97
|
+
watch(listener, 1, path) do
|
98
|
+
touch 'new_file.rb'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'given a symlink', :unless => windows? do
|
104
|
+
it 'detects the added file' do
|
105
|
+
fixtures do |path|
|
106
|
+
listener.should_receive(:on_change).once.with do |array|
|
107
|
+
array.should include(path)
|
108
|
+
end
|
109
|
+
|
110
|
+
touch 'new_file.rb'
|
111
|
+
|
112
|
+
watch(listener, 1, path) do
|
113
|
+
ln_s 'new_file.rb', 'new_file_symlink.rb'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'given a new created directory' do
|
120
|
+
it 'detects the added file' do
|
121
|
+
fixtures do |path|
|
122
|
+
listener.should_receive(:on_change).once.with do |array|
|
123
|
+
array.should include(path, "#{path}/a_directory")
|
124
|
+
end
|
125
|
+
|
126
|
+
watch(listener, 2, path) do
|
127
|
+
mkdir 'a_directory'
|
128
|
+
# Needed for INotify, because of :recursive rb-inotify custom flag?
|
129
|
+
sleep 0.05
|
130
|
+
touch 'a_directory/new_file.rb'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'given an existing directory' do
|
137
|
+
it 'detects the added file' do
|
138
|
+
fixtures do |path|
|
139
|
+
listener.should_receive(:on_change).once.with do |array|
|
140
|
+
array.should include("#{path}/a_directory")
|
141
|
+
end
|
142
|
+
|
143
|
+
mkdir 'a_directory'
|
144
|
+
|
145
|
+
watch(listener, 1, path) do
|
146
|
+
touch 'a_directory/new_file.rb'
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'given a directory with subdirectories' do
|
153
|
+
it 'detects the added file' do
|
154
|
+
fixtures do |path|
|
155
|
+
listener.should_receive(:on_change).once.with do |array|
|
156
|
+
array.should include("#{path}/a_directory/subdirectory")
|
157
|
+
end
|
158
|
+
|
159
|
+
mkdir_p 'a_directory/subdirectory'
|
160
|
+
|
161
|
+
watch(listener, 1, path) do
|
162
|
+
touch 'a_directory/subdirectory/new_file.rb'
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'when a file is modified' do
|
170
|
+
it 'detects the modified file' do
|
171
|
+
fixtures do |path|
|
172
|
+
listener.should_receive(:on_change).once.with do |array|
|
173
|
+
array.should include(path)
|
174
|
+
end
|
175
|
+
|
176
|
+
touch 'existing_file.txt'
|
177
|
+
|
178
|
+
watch(listener, 1, path) do
|
179
|
+
touch 'existing_file.txt'
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'given a symlink', :unless => windows? do
|
185
|
+
it 'detects the modified file' do
|
186
|
+
fixtures do |path|
|
187
|
+
listener.should_receive(:on_change).once.with do |array|
|
188
|
+
array.should include(path)
|
189
|
+
end
|
190
|
+
|
191
|
+
touch 'existing_file.rb'
|
192
|
+
ln_s 'existing_file.rb', 'existing_file_symlink.rb'
|
193
|
+
|
194
|
+
watch(listener, 1, path) do
|
195
|
+
touch 'existing_file.rb'
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'given a hidden file' do
|
202
|
+
it 'detects the modified file' do
|
203
|
+
fixtures do |path|
|
204
|
+
listener.should_receive(:on_change).once.with do |array|
|
205
|
+
array.should include(path)
|
206
|
+
end
|
207
|
+
|
208
|
+
touch '.hidden'
|
209
|
+
|
210
|
+
watch(listener, 1, path) do
|
211
|
+
touch '.hidden'
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context 'given a file mode change', :unless => windows? do
|
218
|
+
it 'does not detect the mode change' do
|
219
|
+
fixtures do |path|
|
220
|
+
listener.should_receive(:on_change).once.with do |array|
|
221
|
+
array.should include(path)
|
222
|
+
end
|
223
|
+
|
224
|
+
touch 'run.rb'
|
225
|
+
|
226
|
+
watch(listener, 1, path) do
|
227
|
+
chmod 0777, 'run.rb'
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
context 'given an existing directory' do
|
234
|
+
it 'detects the modified file' do
|
235
|
+
fixtures do |path|
|
236
|
+
listener.should_receive(:on_change).once.with do |array|
|
237
|
+
array.should include("#{path}/a_directory")
|
238
|
+
end
|
239
|
+
|
240
|
+
mkdir 'a_directory'
|
241
|
+
touch 'a_directory/existing_file.txt'
|
242
|
+
|
243
|
+
watch(listener, 1, path) do
|
244
|
+
touch 'a_directory/existing_file.txt'
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
context 'given a directory with subdirectories' do
|
251
|
+
it 'detects the modified file' do
|
252
|
+
fixtures do |path|
|
253
|
+
listener.should_receive(:on_change).once.with do |array|
|
254
|
+
array.should include("#{path}/a_directory/subdirectory")
|
255
|
+
end
|
256
|
+
|
257
|
+
mkdir_p 'a_directory/subdirectory'
|
258
|
+
touch 'a_directory/subdirectory/existing_file.txt'
|
259
|
+
|
260
|
+
watch(listener, 1, path) do
|
261
|
+
touch 'a_directory/subdirectory/new_file.rb'
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
context 'when a file is moved' do
|
269
|
+
it 'detects the file move' do
|
270
|
+
fixtures do |path|
|
271
|
+
listener.should_receive(:on_change).once.with do |array|
|
272
|
+
array.should include(path)
|
273
|
+
end
|
274
|
+
|
275
|
+
touch 'move_me.txt'
|
276
|
+
|
277
|
+
watch(listener, 1, path) do
|
278
|
+
mv 'move_me.txt', 'new_name.txt'
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'given a symlink', :unless => windows? do
|
284
|
+
it 'detects the file move' do
|
285
|
+
fixtures do |path|
|
286
|
+
listener.should_receive(:on_change).once.with do |array|
|
287
|
+
array.should include(path)
|
288
|
+
end
|
289
|
+
|
290
|
+
touch 'move_me.rb'
|
291
|
+
ln_s 'move_me.rb', 'move_me_symlink.rb'
|
292
|
+
|
293
|
+
watch(listener, 1, path) do
|
294
|
+
mv 'move_me_symlink.rb', 'new_symlink.rb'
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context 'given an existing directory' do
|
301
|
+
it 'detects the file move into the directory' do
|
302
|
+
fixtures do |path|
|
303
|
+
listener.should_receive(:on_change).once.with do |array|
|
304
|
+
array.should include(path, "#{path}/a_directory")
|
305
|
+
end
|
306
|
+
|
307
|
+
mkdir 'a_directory'
|
308
|
+
touch 'move_me.txt'
|
309
|
+
|
310
|
+
watch(listener, 2, path) do
|
311
|
+
mv 'move_me.txt', 'a_directory/move_me.txt'
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
it 'detects a file move out of the directory' do
|
317
|
+
fixtures do |path|
|
318
|
+
listener.should_receive(:on_change).once.with do |array|
|
319
|
+
array.should include(path, "#{path}/a_directory")
|
320
|
+
end
|
321
|
+
|
322
|
+
mkdir 'a_directory'
|
323
|
+
touch 'a_directory/move_me.txt'
|
324
|
+
|
325
|
+
watch(listener, 2, path) do
|
326
|
+
mv 'a_directory/move_me.txt', 'i_am_here.txt'
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'detects a file move between two directories' do
|
332
|
+
fixtures do |path|
|
333
|
+
listener.should_receive(:on_change).once.with do |array|
|
334
|
+
array.should include("#{path}/from_directory", "#{path}/to_directory")
|
335
|
+
end
|
336
|
+
|
337
|
+
mkdir 'from_directory'
|
338
|
+
touch 'from_directory/move_me.txt'
|
339
|
+
mkdir 'to_directory'
|
340
|
+
|
341
|
+
watch(listener, 2, path) do
|
342
|
+
mv 'from_directory/move_me.txt', 'to_directory/move_me.txt'
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
context 'given a directory with subdirectories' do
|
349
|
+
it 'detects files movements between subdirectories' do
|
350
|
+
fixtures do |path|
|
351
|
+
listener.should_receive(:on_change).once.with do |array|
|
352
|
+
array.should include("#{path}/a_directory/subdirectory", "#{path}/b_directory/subdirectory")
|
353
|
+
end
|
354
|
+
|
355
|
+
mkdir_p 'a_directory/subdirectory'
|
356
|
+
mkdir_p 'b_directory/subdirectory'
|
357
|
+
touch 'a_directory/subdirectory/move_me.txt'
|
358
|
+
|
359
|
+
watch(listener, 2, path) do
|
360
|
+
mv 'a_directory/subdirectory/move_me.txt', 'b_directory/subdirectory'
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
context 'when a file is deleted' do
|
368
|
+
it 'detects the file removal' do
|
369
|
+
fixtures do |path|
|
370
|
+
listener.should_receive(:on_change).once.with do |array|
|
371
|
+
array.should include(path)
|
372
|
+
end
|
373
|
+
|
374
|
+
touch 'unnecessary.txt'
|
375
|
+
|
376
|
+
watch(listener, 1, path) do
|
377
|
+
rm 'unnecessary.txt'
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
context 'given a symlink', :unless => windows? do
|
383
|
+
it 'detects the file removal' do
|
384
|
+
fixtures do |path|
|
385
|
+
listener.should_receive(:on_change).once.with do |array|
|
386
|
+
array.should include(path)
|
387
|
+
end
|
388
|
+
|
389
|
+
touch 'unnecessary.rb'
|
390
|
+
ln_s 'unnecessary.rb', 'unnecessary_symlink.rb'
|
391
|
+
|
392
|
+
watch(listener, 1, path) do
|
393
|
+
rm 'unnecessary_symlink.rb'
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
context 'given an existing directory' do
|
400
|
+
it 'detects the file removal' do
|
401
|
+
fixtures do |path|
|
402
|
+
listener.should_receive(:on_change).once.with do |array|
|
403
|
+
array.should include("#{path}/a_directory")
|
404
|
+
end
|
405
|
+
|
406
|
+
mkdir 'a_directory'
|
407
|
+
touch 'a_directory/do_not_use.rb'
|
408
|
+
|
409
|
+
watch(listener, 1, path) do
|
410
|
+
rm 'a_directory/do_not_use.rb'
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
context 'given a directory with subdirectories' do
|
417
|
+
it 'detects the file removal' do
|
418
|
+
fixtures do |path|
|
419
|
+
listener.should_receive(:on_change).once.with do |array|
|
420
|
+
array.should include("#{path}/a_directory/subdirectory")
|
421
|
+
end
|
422
|
+
|
423
|
+
mkdir_p 'a_directory/subdirectory'
|
424
|
+
touch 'a_directory/subdirectory/do_not_use.rb'
|
425
|
+
|
426
|
+
watch(listener, 1, path) do
|
427
|
+
rm 'a_directory/subdirectory/do_not_use.rb'
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
context 'multiple file operations' do
|
436
|
+
it 'detects the added files' do
|
437
|
+
fixtures do |path|
|
438
|
+
listener.should_receive(:on_change).once.with do |array|
|
439
|
+
array.should include(path, "#{path}/a_directory")
|
440
|
+
end
|
441
|
+
|
442
|
+
watch(listener, 2, path) do
|
443
|
+
touch 'a_file.rb'
|
444
|
+
touch 'b_file.rb'
|
445
|
+
mkdir 'a_directory'
|
446
|
+
# Needed for INotify, because of :recursive rb-inotify custom flag?
|
447
|
+
# Also needed for the osx adapter
|
448
|
+
sleep 0.05
|
449
|
+
touch 'a_directory/a_file.rb'
|
450
|
+
touch 'a_directory/b_file.rb'
|
451
|
+
end
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
it 'detects the modified files' do
|
456
|
+
fixtures do |path|
|
457
|
+
listener.should_receive(:on_change).once.with do |array|
|
458
|
+
array.should include(path, "#{path}/a_directory")
|
459
|
+
end
|
460
|
+
|
461
|
+
touch 'a_file.rb'
|
462
|
+
touch 'b_file.rb'
|
463
|
+
mkdir 'a_directory'
|
464
|
+
touch 'a_directory/a_file.rb'
|
465
|
+
touch 'a_directory/b_file.rb'
|
466
|
+
|
467
|
+
watch(listener, 2, path) do
|
468
|
+
touch 'b_file.rb'
|
469
|
+
touch 'a_directory/a_file.rb'
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
it 'detects the removed files' do
|
475
|
+
fixtures do |path|
|
476
|
+
listener.should_receive(:on_change).once.with do |array|
|
477
|
+
array.should include(path, "#{path}/a_directory")
|
478
|
+
end
|
479
|
+
|
480
|
+
touch 'a_file.rb'
|
481
|
+
touch 'b_file.rb'
|
482
|
+
mkdir 'a_directory'
|
483
|
+
touch 'a_directory/a_file.rb'
|
484
|
+
touch 'a_directory/b_file.rb'
|
485
|
+
|
486
|
+
watch(listener, 2, path) do
|
487
|
+
rm 'b_file.rb'
|
488
|
+
rm 'a_directory/a_file.rb'
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
context 'single directory operations' do
|
495
|
+
it 'detects a moved directory' do
|
496
|
+
fixtures do |path|
|
497
|
+
listener.should_receive(:on_change).once.with do |array|
|
498
|
+
array.should include(path)
|
499
|
+
end
|
500
|
+
|
501
|
+
mkdir 'a_directory'
|
502
|
+
touch 'a_directory/a_file.rb'
|
503
|
+
touch 'a_directory/b_file.rb'
|
504
|
+
|
505
|
+
watch(listener, 1, path) do
|
506
|
+
mv 'a_directory', 'renamed'
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
it 'detects a removed directory' do
|
512
|
+
fixtures do |path|
|
513
|
+
listener.should_receive(:on_change).once.with do |array|
|
514
|
+
array.should include(path, "#{path}/a_directory")
|
515
|
+
end
|
516
|
+
|
517
|
+
mkdir 'a_directory'
|
518
|
+
touch 'a_directory/a_file.rb'
|
519
|
+
touch 'a_directory/b_file.rb'
|
520
|
+
|
521
|
+
watch(listener, 2, path) do
|
522
|
+
rm_rf 'a_directory'
|
523
|
+
end
|
524
|
+
end
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
context "paused adapter" do
|
529
|
+
context 'when a file is created' do
|
530
|
+
it "doesn't detects the added file" do
|
531
|
+
fixtures do |path|
|
532
|
+
watch(listener, 1, path) do # The expected changes param is set to one!
|
533
|
+
@adapter.paused = true
|
534
|
+
touch 'new_file.rb'
|
535
|
+
end
|
536
|
+
@called.should be_nil
|
537
|
+
end
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
context "when multiple directories are listened to" do
|
543
|
+
context 'when files are added to one of multiple directories' do
|
544
|
+
it 'detects added files' do
|
545
|
+
fixtures(2) do |path1, path2|
|
546
|
+
listener.should_receive(:on_change).once.with do |array|
|
547
|
+
array.should include(path2)
|
548
|
+
end
|
549
|
+
|
550
|
+
watch(listener, 1, path1, path2) do
|
551
|
+
touch "#{path2}/new_file.rb"
|
552
|
+
end
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
context 'when files are added to multiple directories' do
|
558
|
+
it 'detects added files' do
|
559
|
+
fixtures(2) do |path1, path2|
|
560
|
+
listener.should_receive(:on_change).once.with do |array|
|
561
|
+
array.should include(path1, path2)
|
562
|
+
end
|
563
|
+
|
564
|
+
watch(listener, 2, path1, path2) do
|
565
|
+
touch "#{path1}/new_file.rb"
|
566
|
+
touch "#{path2}/new_file.rb"
|
567
|
+
end
|
568
|
+
end
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
context 'given a new and an existing directory on multiple directories' do
|
573
|
+
it 'detects the added file' do
|
574
|
+
fixtures(2) do |path1, path2|
|
575
|
+
listener.should_receive(:on_change).once.with do |array|
|
576
|
+
array.should include(path2, "#{path1}/a_directory", "#{path2}/b_directory")
|
577
|
+
end
|
578
|
+
|
579
|
+
mkdir "#{path1}/a_directory"
|
580
|
+
|
581
|
+
watch(listener, 3, path1, path2) do
|
582
|
+
mkdir "#{path2}/b_directory"
|
583
|
+
# Needed for INotify
|
584
|
+
sleep 0.05
|
585
|
+
touch "#{path1}/a_directory/new_file.rb"
|
586
|
+
touch "#{path2}/b_directory/new_file.rb"
|
587
|
+
end
|
588
|
+
end
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
592
|
+
context 'when a file is moved between the multiple watched directories' do
|
593
|
+
it 'detects the movements of the file' do
|
594
|
+
fixtures(3) do |path1, path2, path3|
|
595
|
+
listener.should_receive(:on_change).once.with do |array|
|
596
|
+
array.should include("#{path1}/from_directory", path2, "#{path3}/to_directory")
|
597
|
+
end
|
598
|
+
|
599
|
+
mkdir "#{path1}/from_directory"
|
600
|
+
touch "#{path1}/from_directory/move_me.txt"
|
601
|
+
mkdir "#{path3}/to_directory"
|
602
|
+
|
603
|
+
watch(listener, 3, path1, path2, path3) do
|
604
|
+
mv "#{path1}/from_directory/move_me.txt", "#{path2}/move_me.txt"
|
605
|
+
mv "#{path2}/move_me.txt", "#{path3}/to_directory/move_me.txt"
|
606
|
+
end
|
607
|
+
end
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
context 'when files are deleted from the multiple watched directories' do
|
612
|
+
it 'detects the files removal' do
|
613
|
+
fixtures(2) do |path1, path2|
|
614
|
+
listener.should_receive(:on_change).once.with do |array|
|
615
|
+
array.should include(path1, path2)
|
616
|
+
end
|
617
|
+
|
618
|
+
touch "#{path1}/unnecessary.txt"
|
619
|
+
touch "#{path2}/unnecessary.txt"
|
620
|
+
|
621
|
+
watch(listener, 2, path1, path2) do
|
622
|
+
rm "#{path1}/unnecessary.txt"
|
623
|
+
rm "#{path2}/unnecessary.txt"
|
624
|
+
end
|
625
|
+
end
|
626
|
+
end
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Prepares a record for the test and fetches changes
|
2
|
+
# afterwards.
|
3
|
+
#
|
4
|
+
# @param [String] root_path the path to watch
|
5
|
+
# @param [Hash] options
|
6
|
+
# @option options [Array<string>] :paths optional paths fetch changes for
|
7
|
+
# @option options [Boolean] :use_last_record allow the use of an already
|
8
|
+
# created record, handy for ordered tests.
|
9
|
+
#
|
10
|
+
# @return [Array, Array, Array] the changes
|
11
|
+
#
|
12
|
+
def changes(root_path, options = {})
|
13
|
+
unless @record || options[:use_last_record]
|
14
|
+
@record = Listen::DirectoryRecord.new(root_path)
|
15
|
+
@record.filter(options.delete(:filter)) if options[:filter]
|
16
|
+
@record.ignore(options.delete(:ignore)) if options[:ignore]
|
17
|
+
|
18
|
+
# Build the record after adding the filtering and ignoring patterns
|
19
|
+
@record.build
|
20
|
+
end
|
21
|
+
|
22
|
+
yield if block_given?
|
23
|
+
|
24
|
+
paths = options.delete(:paths) || [root_path]
|
25
|
+
options[:recursive] = true if options[:recursive].nil?
|
26
|
+
|
27
|
+
changes = @record.fetch_changes(paths, {:relative_paths => true}.merge(options))
|
28
|
+
|
29
|
+
[changes[:modified], changes[:added], changes[:removed]]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Generates a small time difference before performing a time sensitive
|
33
|
+
# task (like comparing mtimes of files).
|
34
|
+
#
|
35
|
+
# @note Modification time for files only includes the milliseconds on Linux with MRI > 1.9.2,
|
36
|
+
# that's why we generate a difference that's greater than 1 second.
|
37
|
+
#
|
38
|
+
def small_time_difference
|
39
|
+
t = Time.now
|
40
|
+
diff = t.to_f - t.to_i
|
41
|
+
|
42
|
+
sleep( 1.5 - (diff < 0.5 ? diff : 0.4) )
|
43
|
+
end
|
44
|
+
|
45
|
+
# Ensures that the test runs at almost the same second at which
|
46
|
+
# changes are being checked.
|
47
|
+
#
|
48
|
+
def ensure_same_second
|
49
|
+
t = Time.now
|
50
|
+
diff = t.to_f - t.to_i
|
51
|
+
|
52
|
+
if diff > 0.1 # We are not at the beginning of a second
|
53
|
+
sleep 1.1 - diff # 1.1 is used instead of 1 to account for the processing time (estimated at 0.1 sec)
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
include FileUtils
|
4
|
+
|
5
|
+
# Prepares temporary fixture-directories and
|
6
|
+
# cleans them afterwards.
|
7
|
+
#
|
8
|
+
# @param [Fixnum] number_of_directories the number of fixture-directories to make
|
9
|
+
#
|
10
|
+
# @yield [path1, path2, ...] the empty fixture-directories
|
11
|
+
# @yieldparam [String] path the path to a fixture directory
|
12
|
+
#
|
13
|
+
def fixtures(number_of_directories = 1)
|
14
|
+
current_pwd = pwd
|
15
|
+
paths = 1.upto(number_of_directories).map do
|
16
|
+
File.expand_path(File.join(pwd, "spec/.fixtures/#{Time.now.to_f.to_s.sub('.', '') + rand(9999).to_s}"))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Create the dirs
|
20
|
+
paths.each { |p| mkdir_p(p) }
|
21
|
+
|
22
|
+
cd(paths.first) if number_of_directories == 1
|
23
|
+
|
24
|
+
yield(*paths)
|
25
|
+
|
26
|
+
ensure
|
27
|
+
cd current_pwd
|
28
|
+
paths.map { |p| rm_rf(p) if File.exists?(p) }
|
29
|
+
end
|