sass 3.2.0.alpha.101 → 3.2.0.alpha.102

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 (45) hide show
  1. data/REVISION +1 -1
  2. data/Rakefile +2 -2
  3. data/VERSION +1 -1
  4. data/lib/sass/plugin/compiler.rb +25 -32
  5. data/lib/sass/plugin/listener.rb +59 -0
  6. data/lib/sass/script/lexer.rb +1 -1
  7. data/lib/sass/script/list.rb +1 -0
  8. data/test/sass/conversion_test.rb +10 -0
  9. data/test/sass/scss/css_test.rb +9 -0
  10. data/vendor/listen/CHANGELOG.md +72 -0
  11. data/vendor/listen/Gemfile +35 -0
  12. data/vendor/listen/Guardfile +8 -0
  13. data/vendor/listen/LICENSE +20 -0
  14. data/vendor/listen/README.md +297 -0
  15. data/vendor/listen/Rakefile +47 -0
  16. data/vendor/listen/Vagrantfile +96 -0
  17. data/vendor/listen/lib/listen.rb +38 -0
  18. data/vendor/listen/lib/listen/adapter.rb +159 -0
  19. data/vendor/listen/lib/listen/adapters/darwin.rb +84 -0
  20. data/vendor/listen/lib/listen/adapters/linux.rb +99 -0
  21. data/vendor/listen/lib/listen/adapters/polling.rb +66 -0
  22. data/vendor/listen/lib/listen/adapters/windows.rb +82 -0
  23. data/vendor/listen/lib/listen/directory_record.rb +257 -0
  24. data/vendor/listen/lib/listen/listener.rb +186 -0
  25. data/vendor/listen/lib/listen/multi_listener.rb +121 -0
  26. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  27. data/vendor/listen/lib/listen/version.rb +3 -0
  28. data/vendor/listen/listen.gemspec +26 -0
  29. data/vendor/listen/spec/listen/adapter_spec.rb +142 -0
  30. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +31 -0
  31. data/vendor/listen/spec/listen/adapters/linux_spec.rb +30 -0
  32. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  33. data/vendor/listen/spec/listen/adapters/windows_spec.rb +24 -0
  34. data/vendor/listen/spec/listen/directory_record_spec.rb +807 -0
  35. data/vendor/listen/spec/listen/listener_spec.rb +151 -0
  36. data/vendor/listen/spec/listen/multi_listener_spec.rb +151 -0
  37. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  38. data/vendor/listen/spec/listen_spec.rb +73 -0
  39. data/vendor/listen/spec/spec_helper.rb +16 -0
  40. data/vendor/listen/spec/support/adapter_helper.rb +538 -0
  41. data/vendor/listen/spec/support/directory_record_helper.rb +35 -0
  42. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  43. data/vendor/listen/spec/support/listeners_helper.rb +133 -0
  44. data/vendor/listen/spec/support/platform_helper.rb +11 -0
  45. metadata +41 -5
@@ -0,0 +1,121 @@
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 [String] ignore a list of paths to ignore
10
+ # @option options [Regexp] filter a list of regexps file filters
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
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 { @adapter = initialize_adapter }
42
+ @directories_records.each { |r| r.build }
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
+ # Adds file filters to the listener.
69
+ #
70
+ # @param (see Listen::DirectoryRecord#filter)
71
+ #
72
+ # @return [Listen::Listener] the listener
73
+ #
74
+ def filter(*regexps)
75
+ @directories_records.each { |r| r.filter(*regexps) }
76
+ self
77
+ end
78
+
79
+ # Runs the callback passing it the changes if there are any.
80
+ #
81
+ # @param (see Listen::DirectoryRecord#fetch_changes)
82
+ #
83
+ def on_change(directories_to_search, options = {})
84
+ changes = fetch_records_changes(directories_to_search, options)
85
+ unless changes.values.all? { |paths| paths.empty? }
86
+ @block.call(changes[:modified],changes[:added],changes[:removed])
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ # Initializes an adapter passing it the callback and adapters' options.
93
+ #
94
+ def initialize_adapter
95
+ callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
96
+ Adapter.select_and_initialize(@directories, @adapter_options, &callback)
97
+ end
98
+
99
+ # Returns the sum of all the changes to the directories records
100
+ #
101
+ # @param (see Listen::DirectoryRecord#fetch_changes)
102
+ #
103
+ # @return [Hash] the changes
104
+ #
105
+ def fetch_records_changes(directories_to_search, options)
106
+ @directories_records.inject({}) do |h, r|
107
+ # directory records skips paths outside their range, so passing the
108
+ # whole `directories` array is not a problem.
109
+ record_changes = r.fetch_changes(directories_to_search, options.merge(:relative_paths => DEFAULT_TO_RELATIVE_PATHS))
110
+
111
+ if h.empty?
112
+ h.merge!(record_changes)
113
+ else
114
+ h.each { |k, v| h[k] += record_changes[k] }
115
+ end
116
+
117
+ h
118
+ end
119
+ end
120
+ end
121
+ 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,3 @@
1
+ module Listen
2
+ VERSION = '0.4.1'
3
+ end
@@ -0,0 +1,26 @@
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_dependency 'rb-fsevent', '~> 0.9.1'
19
+ s.add_dependency 'rb-inotify', '~> 0.8.8'
20
+ s.add_dependency 'rb-fchange', '~> 0.0.5'
21
+
22
+ s.add_development_dependency 'bundler'
23
+
24
+ s.files = Dir.glob('{lib}/**/*') + %w[CHANGELOG.md LICENSE README.md]
25
+ s.require_path = 'lib'
26
+ end
@@ -0,0 +1,142 @@
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::Windows.stub(:usable_and_works?) { false }
25
+ end
26
+
27
+ context "with no specific adapter usable" do
28
+ it "returns Listen::Adapters::Polling instance" do
29
+ Kernel.stub(:warn)
30
+ Listen::Adapters::Polling.should_receive(:new).with('dir', {})
31
+ described_class.select_and_initialize('dir')
32
+ end
33
+
34
+ it "warns with the default polling fallback message" do
35
+ Kernel.should_receive(:warn).with(Listen::Adapter::POLLING_FALLBACK_MESSAGE)
36
+ described_class.select_and_initialize('dir')
37
+ end
38
+
39
+ context "with custom polling_fallback_message option" do
40
+ it "warns with the custom polling fallback message" do
41
+ Kernel.should_receive(:warn).with('custom')
42
+ described_class.select_and_initialize('dir', :polling_fallback_message => 'custom')
43
+ end
44
+ end
45
+
46
+ context "with polling_fallback_message to false" do
47
+ it "doesn't warn with a polling fallback message" do
48
+ Kernel.should_not_receive(:warn)
49
+ described_class.select_and_initialize('dir', :polling_fallback_message => false)
50
+ end
51
+ end
52
+ end
53
+
54
+ context "on Mac OX >= 10.6" do
55
+ before { Listen::Adapters::Darwin.stub(:usable_and_works?) { true } }
56
+
57
+ it "uses Listen::Adapters::Darwin" do
58
+ Listen::Adapters::Darwin.should_receive(:new).with('dir', {})
59
+ described_class.select_and_initialize('dir')
60
+ end
61
+
62
+ context 'when the use of the polling adapter is forced' do
63
+ it 'uses Listen::Adapters::Polling' do
64
+ Listen::Adapters::Polling.should_receive(:new).with('dir', {})
65
+ described_class.select_and_initialize('dir', :force_polling => true)
66
+ end
67
+ end
68
+ end
69
+
70
+ context "on Linux" do
71
+ before { Listen::Adapters::Linux.stub(:usable_and_works?) { true } }
72
+
73
+ it "uses Listen::Adapters::Linux" do
74
+ Listen::Adapters::Linux.should_receive(:new).with('dir', {})
75
+ described_class.select_and_initialize('dir')
76
+ end
77
+
78
+ context 'when the use of the polling adapter is forced' do
79
+ it 'uses Listen::Adapters::Polling' do
80
+ Listen::Adapters::Polling.should_receive(:new).with('dir', {})
81
+ described_class.select_and_initialize('dir', :force_polling => true)
82
+ end
83
+ end
84
+ end
85
+
86
+ context "on Windows" do
87
+ before { Listen::Adapters::Windows.stub(:usable_and_works?) { true } }
88
+
89
+ it "uses Listen::Adapters::Windows" do
90
+ Listen::Adapters::Windows.should_receive(:new).with('dir', {})
91
+ described_class.select_and_initialize('dir')
92
+ end
93
+
94
+ context 'when the use of the polling adapter is forced' do
95
+ it 'uses Listen::Adapters::Polling' do
96
+ Listen::Adapters::Polling.should_receive(:new).with('dir', {})
97
+ described_class.select_and_initialize('dir', :force_polling => true)
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ [Listen::Adapters::Darwin, Listen::Adapters::Linux, Listen::Adapters::Windows].each do |adapter_class|
104
+ if adapter_class.usable?
105
+ describe '.usable_and_works?' do
106
+ it 'checks if the adapter is usable' do
107
+ adapter_class.stub(:works?)
108
+ adapter_class.should_receive(:usable?)
109
+ adapter_class.usable_and_works?('dir')
110
+ end
111
+
112
+ context 'with one directory' do
113
+ it 'tests if that directory actually work' do
114
+ fixtures do |path|
115
+ adapter_class.should_receive(:works?).with(path, anything).and_return(true)
116
+ adapter_class.usable_and_works?(path)
117
+ end
118
+ end
119
+ end
120
+
121
+ context 'with multiple directories' do
122
+ it 'tests if each directory passed does actually work' do
123
+ fixtures(3) do |path1, path2, path3|
124
+ adapter_class.should_receive(:works?).exactly(3).times.with do |path, options|
125
+ [path1, path2, path3].include? path
126
+ end.and_return(true)
127
+ adapter_class.usable_and_works?([path1, path2, path3])
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ describe '.works?' do
134
+ it 'does work' do
135
+ fixtures do |path|
136
+ adapter_class.works?(path).should be_true
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,31 @@
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
+ end
@@ -0,0 +1,30 @@
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
+ else
13
+ it "isn't usable on Linux with #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}" do
14
+ described_class.should_not be_usable
15
+ end
16
+ end
17
+ end
18
+
19
+ if mac?
20
+ it "isn't usable on Mac OS X" do
21
+ described_class.should_not be_usable
22
+ end
23
+ end
24
+
25
+ if windows?
26
+ it "isn't usable on Windows" do
27
+ described_class.should_not be_usable
28
+ end
29
+ end
30
+ 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