sass 3.2.0.alpha.269 → 3.2.0.alpha.273

Sign up to get free protection for your applications and to get access to all the features.
data/REVISION CHANGED
@@ -1 +1 @@
1
- ce67165e9449e0a708282b04f163a3e8b8a8c370
1
+ 9b1820a2b092ba228eb20bea33b07ddd0793146f
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.2.0.alpha.269
1
+ 3.2.0.alpha.273
@@ -973,23 +973,22 @@ module Sass::Script
973
973
 
974
974
  Sass::Util.check_range("Weight", 0..100, weight, '%')
975
975
 
976
- # This algorithm factors in both the user-provided weight
977
- # and the difference between the alpha values of the two colors
978
- # to decide how to perform the weighted average of the two RGB values.
976
+ # This algorithm factors in both the user-provided weight (w) and the
977
+ # difference between the alpha values of the two colors (a) to decide how
978
+ # to perform the weighted average of the two RGB values.
979
979
  #
980
980
  # It works by first normalizing both parameters to be within [-1, 1],
981
- # where 1 indicates "only use color1", -1 indicates "only use color 0",
982
- # and all values in between indicated a proportionately weighted average.
981
+ # where 1 indicates "only use color1", -1 indicates "only use color2", and
982
+ # all values in between indicated a proportionately weighted average.
983
983
  #
984
- # Once we have the normalized variables w and a,
985
- # we apply the formula (w + a)/(1 + w*a)
986
- # to get the combined weight (in [-1, 1]) of color1.
984
+ # Once we have the normalized variables w and a, we apply the formula
985
+ # (w + a)/(1 + w*a) to get the combined weight (in [-1, 1]) of color1.
987
986
  # This formula has two especially nice properties:
988
987
  #
989
988
  # * When either w or a are -1 or 1, the combined weight is also that number
990
989
  # (cases where w * a == -1 are undefined, and handled as a special case).
991
990
  #
992
- # * When a is 0, the combined weight is w, and vice versa
991
+ # * When a is 0, the combined weight is w, and vice versa.
993
992
  #
994
993
  # Finally, the weight of color1 is renormalized to be within [0, 1]
995
994
  # and the weight of color2 is given by 1 minus the weight of color1.
@@ -36,7 +36,7 @@ module Sass::Script
36
36
  attr_accessor :original
37
37
 
38
38
  def self.precision
39
- @precision ||= 3
39
+ @precision ||= 5
40
40
  end
41
41
 
42
42
  # Sets the number of digits of precision
@@ -73,20 +73,6 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
73
73
  end
74
74
  end
75
75
 
76
- def invalid_function_parent?(parent, child)
77
- "Functions may only be defined at the root of a document." unless parent.is_a?(Sass::Tree::RootNode)
78
- end
79
-
80
- VALID_FUNCTION_CHILDREN = [
81
- Sass::Tree::CommentNode, Sass::Tree::DebugNode, Sass::Tree::ReturnNode,
82
- Sass::Tree::VariableNode, Sass::Tree::WarnNode
83
- ] + CONTROL_NODES
84
- def invalid_function_child?(parent, child)
85
- unless is_any_of?(child, VALID_FUNCTION_CHILDREN)
86
- "Functions can only contain variable declarations and control directives."
87
- end
88
- end
89
-
90
76
  INVALID_IMPORT_PARENTS = CONTROL_NODES +
91
77
  [Sass::Tree::MixinDefNode, Sass::Tree::MixinNode]
92
78
  def invalid_import_parent?(parent, child)
@@ -95,10 +81,6 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
95
81
  end
96
82
  return if parent.is_a?(Sass::Tree::RootNode)
97
83
  return "CSS import directives may only be used at the root of a document." if child.css_import?
98
- # If this is a nested @import, we need to make sure it doesn't have anything
99
- # that's legal at top-level but not in the current context (e.g. mixin defs).
100
- child.imported_file.to_tree.children.each {|c| visit(c)}
101
- nil
102
84
  rescue Sass::SyntaxError => e
103
85
  e.modify_backtrace(:filename => child.imported_file.options[:filename])
104
86
  e.add_backtrace(:filename => child.filename, :line => child.line)
@@ -106,7 +88,25 @@ class Sass::Tree::Visitors::CheckNesting < Sass::Tree::Visitors::Base
106
88
  end
107
89
 
108
90
  def invalid_mixindef_parent?(parent, child)
109
- "Mixins may only be defined at the root of a document." unless parent.is_a?(Sass::Tree::RootNode)
91
+ unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
92
+ return "Mixins may not be defined within control directives or other mixins."
93
+ end
94
+ end
95
+
96
+ def invalid_function_parent?(parent, child)
97
+ unless (@parents.map {|p| p.class} & INVALID_IMPORT_PARENTS).empty?
98
+ return "Functions may not be defined within control directives or other mixins."
99
+ end
100
+ end
101
+
102
+ VALID_FUNCTION_CHILDREN = [
103
+ Sass::Tree::CommentNode, Sass::Tree::DebugNode, Sass::Tree::ReturnNode,
104
+ Sass::Tree::VariableNode, Sass::Tree::WarnNode
105
+ ] + CONTROL_NODES
106
+ def invalid_function_child?(parent, child)
107
+ unless is_any_of?(child, VALID_FUNCTION_CHILDREN)
108
+ "Functions can only contain variable declarations and control directives."
109
+ end
110
110
  end
111
111
 
112
112
  VALID_PROP_CHILDREN = [Sass::Tree::CommentNode, Sass::Tree::PropNode, Sass::Tree::MixinNode] + CONTROL_NODES
@@ -113,7 +113,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
113
113
 
114
114
  # Loads the function into the environment.
115
115
  def visit_function(node)
116
- @environment.set_function(node.name,
116
+ @environment.set_local_function(node.name,
117
117
  Sass::Callable.new(node.name, node.args, @environment, node.children, !:has_content))
118
118
  []
119
119
  end
@@ -155,7 +155,7 @@ class Sass::Tree::Visitors::Perform < Sass::Tree::Visitors::Base
155
155
 
156
156
  # Loads a mixin into the environment.
157
157
  def visit_mixindef(node)
158
- @environment.set_mixin(node.name,
158
+ @environment.set_local_mixin(node.name,
159
159
  Sass::Callable.new(node.name, node.args, @environment, node.children, node.has_content))
160
160
  []
161
161
  end
@@ -59,9 +59,8 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
59
59
  return if node.invisible?
60
60
  spaces = (' ' * [@tabs - node.resolved_value[/^ */].size, 0].max)
61
61
 
62
- content = node.resolved_value.gsub(/^/, spaces).gsub(%r{^(\s*)//(.*)$}) do |md|
63
- "#{$1}/*#{$2} */"
64
- end
62
+ content = node.resolved_value.gsub(/^/, spaces)
63
+ content.gsub!(%r{^(\s*)//(.*)$}) {|md| "#{$1}/*#{$2} */"} if node.type == :silent
65
64
  content.gsub!(/\n +(\* *(?!\/))?/, ' ') if (node.style == :compact || node.style == :compressed) && node.type != :loud
66
65
  content
67
66
  end
@@ -73,7 +73,7 @@ MSG
73
73
  "=foo\n :color red\n.bar\n +bang" => "Undefined mixin 'bang'.",
74
74
  "=foo\n :color red\n.bar\n +bang_bop" => "Undefined mixin 'bang_bop'.",
75
75
  "=foo\n :color red\n.bar\n +bang-bop" => "Undefined mixin 'bang-bop'.",
76
- ".bar\n =foo\n :color red\n" => ["Mixins may only be defined at the root of a document.", 2],
76
+ ".foo\n =foo\n :color red\n.bar\n +foo" => "Undefined mixin 'foo'.",
77
77
  " a\n b: c" => ["Indenting at the beginning of the document is illegal.", 1],
78
78
  " \n \n\t\n a\n b: c" => ["Indenting at the beginning of the document is illegal.", 4],
79
79
  "a\n b: c\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 3],
@@ -105,7 +105,6 @@ MSG
105
105
  "@function foo($)\n @return 1" => ['Invalid CSS after "(": expected variable (e.g. $foo), was "$)"', 1],
106
106
  "@function foo()\n @return" => 'Invalid @return: expected expression.',
107
107
  "@function foo()\n @return 1\n $var: val" => 'Illegal nesting: Nothing may be nested beneath return directives.',
108
- "foo\n @function bar()\n @return 1" => ['Functions may only be defined at the root of a document.', 2],
109
108
  "@function foo($a)\n @return 1\na\n b: foo()" => 'Function foo is missing argument $a',
110
109
  "@function foo()\n @return 1\na\n b: foo(2)" => 'Wrong number of arguments (1 for 0) for `foo\'',
111
110
  "@function foo()\n @return 1\na\n b: foo($a: 1)" => "Function foo doesn't have an argument named $a",
@@ -274,7 +273,7 @@ SASS
274
273
  end
275
274
 
276
275
  def test_imported_exception
277
- [1, 2, 3, 4, 5].each do |i|
276
+ [1, 2, 3, 4].each do |i|
278
277
  begin
279
278
  Sass::Engine.new("@import bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
280
279
  rescue Sass::SyntaxError => err
@@ -296,7 +295,7 @@ SASS
296
295
  end
297
296
 
298
297
  def test_double_imported_exception
299
- [1, 2, 3, 4, 5].each do |i|
298
+ [1, 2, 3, 4].each do |i|
300
299
  begin
301
300
  Sass::Engine.new("@import nested_bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
302
301
  rescue Sass::SyntaxError => err
@@ -723,24 +722,6 @@ CSS
723
722
  SASS
724
723
  end
725
724
 
726
- def test_nested_import_with_toplevel_constructs
727
- Sass::Engine.new(".foo\n @import importee", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
728
- rescue Sass::SyntaxError => err
729
- assert_equal(3, err.sass_line)
730
- assert_match(/(\/|^)importee\.sass$/, err.sass_filename)
731
-
732
- assert_hash_has(err.sass_backtrace.first,
733
- :filename => err.sass_filename, :line => err.sass_line)
734
-
735
- assert_nil(err.sass_backtrace[1][:filename])
736
- assert_equal(2, err.sass_backtrace[1][:line])
737
-
738
- assert_match(/(\/|^)importee\.sass:3$/, err.backtrace.first)
739
- assert_equal("(sass):2", err.backtrace[1])
740
- else
741
- assert(false, "Exception not raised for importing mixins nested")
742
- end
743
-
744
725
  def test_units
745
726
  renders_correctly "units"
746
727
  end
@@ -1027,6 +1027,21 @@ bar {baz: bang}
1027
1027
  SCSS
1028
1028
  end
1029
1029
 
1030
+ def test_single_line_comment_within_multiline_comment
1031
+ assert_equal(<<CSS, render(<<SCSS))
1032
+ body {
1033
+ /*
1034
+ //comment here
1035
+ */ }
1036
+ CSS
1037
+ body {
1038
+ /*
1039
+ //comment here
1040
+ */
1041
+ }
1042
+ SCSS
1043
+ end
1044
+
1030
1045
  private
1031
1046
 
1032
1047
  def assert_selector_parses(selector)
@@ -1073,17 +1073,83 @@ $domain: "sass-lang.com";
1073
1073
  SCSS
1074
1074
  end
1075
1075
 
1076
+ def test_nested_mixin_def
1077
+ assert_equal <<CSS, render(<<SCSS)
1078
+ foo {
1079
+ a: b; }
1080
+ CSS
1081
+ foo {
1082
+ @mixin bar {a: b}
1083
+ @include bar; }
1084
+ SCSS
1085
+ end
1086
+
1087
+ def test_nested_mixin_shadow
1088
+ assert_equal <<CSS, render(<<SCSS)
1089
+ foo {
1090
+ c: d; }
1091
+
1092
+ baz {
1093
+ a: b; }
1094
+ CSS
1095
+ @mixin bar {a: b}
1096
+
1097
+ foo {
1098
+ @mixin bar {c: d}
1099
+ @include bar;
1100
+ }
1101
+
1102
+ baz {@include bar}
1103
+ SCSS
1104
+ end
1105
+
1106
+ def test_nested_function_def
1107
+ assert_equal <<CSS, render(<<SCSS)
1108
+ foo {
1109
+ a: 1; }
1110
+
1111
+ bar {
1112
+ b: foo(); }
1113
+ CSS
1114
+ foo {
1115
+ @function foo() {@return 1}
1116
+ a: foo(); }
1117
+
1118
+ bar {b: foo()}
1119
+ SCSS
1120
+ end
1121
+
1122
+ def test_nested_function_shadow
1123
+ assert_equal <<CSS, render(<<SCSS)
1124
+ foo {
1125
+ a: 2; }
1126
+
1127
+ baz {
1128
+ b: 1; }
1129
+ CSS
1130
+ @function foo() {@return 1}
1131
+
1132
+ foo {
1133
+ @function foo() {@return 2}
1134
+ a: foo();
1135
+ }
1136
+
1137
+ baz {b: foo()}
1138
+ SCSS
1139
+ end
1140
+
1076
1141
  ## Errors
1077
1142
 
1078
- def test_mixin_defs_only_at_toplevel
1143
+ def test_nested_mixin_def_is_scoped
1079
1144
  render <<SCSS
1080
1145
  foo {
1081
1146
  @mixin bar {a: b}}
1147
+ bar {@include bar}
1082
1148
  SCSS
1083
1149
  assert(false, "Expected syntax error")
1084
1150
  rescue Sass::SyntaxError => e
1085
- assert_equal "Mixins may only be defined at the root of a document.", e.message
1086
- assert_equal 2, e.sass_line
1151
+ assert_equal "Undefined mixin 'bar'.", e.message
1152
+ assert_equal 3, e.sass_line
1087
1153
  end
1088
1154
 
1089
1155
  def test_rules_beneath_properties
@@ -1,23 +1,63 @@
1
+ ## 0.4.7 - June 27, 2012
2
+
3
+ ### Bug fixes
4
+
5
+ - Increase latency to 0.25, to avoid useless polling fallback. (fixed by [@thibaudgg][])
6
+ - Change watched inotify events, to avoid duplication callback. (fixed by [@thibaudgg][])
7
+ - [#41](https://github.com/guard/listen/issues/41) Use lstat instead of stat when calculating mtime. (fixed by [@ebroder][])
8
+
9
+ ## 0.4.6 - June 20, 2012
10
+
11
+ ### Bug fix
12
+
13
+ - [#39](https://github.com/guard/listen/issues/39) Fix digest race condition. (fixed by [@dkubb][])
14
+
15
+ ## 0.4.5 - June 13, 2012
16
+
17
+ ### Bug fix
18
+
19
+ - [#39](https://github.com/guard/listen/issues/39) Rescue Errno::ENOENT when path inserted doesn't exist. (reported by [@textgoeshere][], fixed by [@thibaudgg][] and [@rymai][])
20
+
21
+ ## 0.4.4 - June 8, 2012
22
+
23
+ ### Bug fixes
24
+
25
+ - ~~[#39](https://github.com/guard/listen/issues/39) Non-existing path insertion bug. (reported by [@textgoeshere][], fixed by [@thibaudgg][])~~
26
+ - Fix relative path for directories containing special characters. (reported by [@napcs][], fixed by [@netzpirat][])
27
+
28
+ ## 0.4.3 - June 6, 2012
29
+
30
+ ### Bug fixes
31
+
32
+ - [#24](https://github.com/guard/listen/issues/24) Fail gracefully when the inotify limit is not enough for Listen to function. (reported by [@daemonza][], fixed by [@Maher4Ever][])
33
+ - [#32](https://github.com/guard/listen/issues/32) Fix a crash when trying to calculate the checksum of unreadable files. (reported by [@nex3][], fixed by [@Maher4Ever][])
34
+
35
+ ### Improvements
36
+
37
+ - Add `#relative_paths` method to listeners. ([@Maher4Ever][])
38
+ - Add `#started?` query-method to adapters. ([@Maher4Ever][])
39
+ - Dynamically detect the mtime precision used on a system. ([@Maher4Ever][] with help from [@nex3][])
40
+
1
41
  ## 0.4.2 - May 1, 2012
2
42
 
3
43
  ### Bug fixes
4
44
 
5
- - [#21](https://github.com/guard/listen/issues/21): Issues when listening to changes in relative paths. (reported by [@akerbos][], fixed by [@Maher4Ever][])
6
- - [#27](https://github.com/guard/listen/issues/27): Wrong reports for files modifications. (reported by [@cobychapple][], fixed by [@Maher4Ever][])
45
+ - [#21](https://github.com/guard/listen/issues/21) Issues when listening to changes in relative paths. (reported by [@akerbos][], fixed by [@Maher4Ever][])
46
+ - [#27](https://github.com/guard/listen/issues/27) Wrong reports for files modifications. (reported by [@cobychapple][], fixed by [@Maher4Ever][])
7
47
  - Fix segmentation fault when profiling on Windows. ([@Maher4Ever][])
8
48
  - Fix redundant watchers on Windows. ([@Maher4Ever][])
9
49
 
10
50
  ### Improvements
11
51
 
12
- - [#17](https://github.com/guard/listen/issues/17): Use regexp-patterns with the `ignore` method instead of supplying paths. (reported by [@fny][], added by [@Maher4Ever][])
52
+ - [#17](https://github.com/guard/listen/issues/17) Use regexp-patterns with the `ignore` method instead of supplying paths. (reported by [@fny][], added by [@Maher4Ever][])
13
53
  - Speed improvement when listening to changes in directories with ignored paths. ([@Maher4Ever][])
14
54
  - Added `.rbx` and `.svn` to ignored directories. ([@Maher4Ever][])
15
55
 
16
56
  ## 0.4.1 - April 15, 2012
17
57
 
18
- ### Bug fixes
58
+ ### Bug fix
19
59
 
20
- - [#18]((https://github.com/guard/listen/issues/18): Listener crashes when removing directories with nested paths. (reported by [@daemonza][], fixed by [@Maher4Ever][])
60
+ - [#18](https://github.com/guard/listen/issues/18) Listener crashes when removing directories with nested paths. (reported by [@daemonza][], fixed by [@Maher4Ever][])
21
61
 
22
62
  ## 0.4.0 - April 9, 2012
23
63
 
@@ -37,19 +77,19 @@
37
77
  - Encapsulate thread spawning in the windows-adapter. ([@Maher4Ever][])
38
78
  - Fix linux-adapter bug where Listen would report file-modification events on the parent-directory. ([@Maher4Ever][])
39
79
 
40
- ### Removals
80
+ ### Change
41
81
 
42
82
  - Remove `wait_until_listening` as adapters doesn't need to run inside threads anymore ([@Maher4Ever][])
43
83
 
44
84
  ## 0.3.3 - March 6, 2012
45
85
 
46
- ### Improvements
86
+ ### Improvement
47
87
 
48
88
  - Improve pause/unpause. ([@thibaudgg][])
49
89
 
50
90
  ## 0.3.2 - March 4, 2012
51
91
 
52
- ### New features
92
+ ### New feature
53
93
 
54
94
  - Add pause/unpause listener's methods. ([@thibaudgg][])
55
95
 
@@ -57,7 +97,7 @@
57
97
 
58
98
  ### Bug fix
59
99
 
60
- - [#9](https://github.com/guard/listen/issues/9): Ignore doesn't seem to work. (reported by [@markiz][], fixed by [@thibaudgg][])
100
+ - [#9](https://github.com/guard/listen/issues/9) Ignore doesn't seem to work. (reported by [@markiz][], fixed by [@thibaudgg][])
61
101
 
62
102
  ## 0.3.0 - February 21, 2012
63
103
 
@@ -81,10 +121,27 @@
81
121
 
82
122
  - First version with only a polling adapter and basic features set (ignore & filter). ([@thibaudgg][])
83
123
 
84
- [@markiz]: https://github.com/markiz
85
- [@thibaudgg]: https://github.com/thibaudgg
124
+ <!--- The following link definition list is generated by PimpMyChangelog --->
125
+ [#9]: https://github.com/guard/listen/issues/9
126
+ [#17]: https://github.com/guard/listen/issues/17
127
+ [#18]: https://github.com/guard/listen/issues/18
128
+ [#21]: https://github.com/guard/listen/issues/21
129
+ [#24]: https://github.com/guard/listen/issues/24
130
+ [#27]: https://github.com/guard/listen/issues/27
131
+ [#32]: https://github.com/guard/listen/issues/32
132
+ [#39]: https://github.com/guard/listen/issues/39
86
133
  [@Maher4Ever]: https://github.com/Maher4Ever
87
- [@daemonza]: https://github.com/daemonza
134
+ [@dkubb]: https://github.com/dkubb
135
+ [@ebroder]: https://github.com/ebroder
88
136
  [@akerbos]: https://github.com/akerbos
89
- [@fny]: https://github.com/fny
90
137
  [@cobychapple]: https://github.com/cobychapple
138
+ [@daemonza]: https://github.com/daemonza
139
+ [@fny]: https://github.com/fny
140
+ [@markiz]: https://github.com/markiz
141
+ [@napcs]: https://github.com/napcs
142
+ [@netzpirat]: https://github.com/netzpirat
143
+ [@nex3]: https://github.com/nex3
144
+ [@rymai]: https://github.com/rymai
145
+ [@scottdavis]: https://github.com/scottdavis
146
+ [@textgoeshere]: https://github.com/textgoeshere
147
+ [@thibaudgg]: https://github.com/thibaudgg
@@ -6,23 +6,11 @@ gem 'rake'
6
6
 
7
7
  group :development do
8
8
  platform :ruby do
9
- gem 'rb-readline'
9
+ gem 'coolline'
10
10
  end
11
11
 
12
- require 'rbconfig'
13
- case RbConfig::CONFIG['target_os']
14
- when /darwin/i
15
- # gem 'ruby_gntp', '~> 0.3.4', :require => false
16
- gem 'growl', :require => false
17
- when /linux/i
18
- gem 'libnotify', '~> 0.7.1', :require => false
19
- when /mswin|mingw/i
20
- gem 'win32console', :require => false
21
- gem 'rb-notifu', '>= 0.0.4', :require => false
22
- end
23
-
24
- gem 'guard', '~> 1.0.0'
25
- gem 'guard-rspec', '~> 0.7.0'
12
+ gem 'guard'
13
+ gem 'guard-rspec'
26
14
  gem 'yard'
27
15
  gem 'redcarpet'
28
16
  gem 'pry'
@@ -31,5 +19,5 @@ group :development do
31
19
  end
32
20
 
33
21
  group :test do
34
- gem 'rspec', '~> 2.9.0'
22
+ gem 'rspec'
35
23
  end
@@ -32,12 +32,12 @@ Feel free to give your feeback via [Listen issues](https://github.com/guard/list
32
32
 
33
33
  ``` ruby
34
34
  # Listen to a single directory.
35
- Listen.to('dir/path/to/listen', filter: /\.rb$/, ignore: %r{ignored/path/}) do |modified, added, removed|
35
+ Listen.to('dir/path/to/listen', :filter => /\.rb$/, :ignore => %r{ignored/path/}) do |modified, added, removed|
36
36
  # ...
37
37
  end
38
38
 
39
39
  # Listen to multiple directories.
40
- Listen.to('dir/to/awesome_app', 'dir/to/other_app', filter: /\.rb$/, latency: 0.1) do |modified, added, removed|
40
+ Listen.to('dir/to/awesome_app', 'dir/to/other_app', :filter => /\.rb$/, :latency => 0.1) do |modified, added, removed|
41
41
  # ...
42
42
  end
43
43
  ```
@@ -191,7 +191,7 @@ These options can be set through `Listen.to` params or via methods (see the "Obj
191
191
  # default: See DEFAULT_IGNORED_DIRECTORIES and DEFAULT_IGNORED_EXTENSIONS in Listen::DirectoryRecord
192
192
 
193
193
  :latency => 0.5 # Set the delay (**in seconds**) between checking for changes
194
- # default: 0.1 sec (1.0 sec for polling)
194
+ # default: 0.25 sec (1.0 sec for polling)
195
195
 
196
196
  :relative_paths => true # Enable the use of relative paths in the callback.
197
197
  # default: false
@@ -8,7 +8,7 @@ module Listen
8
8
  attr_accessor :directories, :latency, :paused
9
9
 
10
10
  # The default delay between checking for changes.
11
- DEFAULT_LATENCY = 0.1
11
+ DEFAULT_LATENCY = 0.25
12
12
 
13
13
  # The default warning message when falling back to polling adapter.
14
14
  POLLING_FALLBACK_MESSAGE = "WARNING: Listen has fallen back to polling, learn more at https://github.com/guard/listen#fallback."
@@ -10,7 +10,7 @@ module Listen
10
10
  # @see http://www.tin.org/bin/man.cgi?section=7&topic=inotify
11
11
  # @see https://github.com/nex3/rb-inotify/blob/master/lib/rb-inotify/notifier.rb#L99-L177
12
12
  #
13
- EVENTS = %w[recursive attrib close modify move create delete delete_self move_self]
13
+ EVENTS = %w[recursive attrib create delete move close_write]
14
14
 
15
15
  # The message to show when the limit of inotify watchers is not enough
16
16
  #
@@ -163,7 +163,7 @@ module Listen
163
163
  #
164
164
  def relative_to_base(path)
165
165
  return nil unless path[@directory]
166
- path.sub(%r{^#{@directory}#{File::SEPARATOR}?}, '')
166
+ path.sub(%r{^#{Regexp.quote(@directory)}#{File::SEPARATOR}?}, '')
167
167
  end
168
168
 
169
169
  private
@@ -239,8 +239,8 @@ module Listen
239
239
  elsif !ignored?(path) && filtered?(path) && !existing_path?(path)
240
240
  if File.file?(path)
241
241
  @changes[:added] << (options[:relative_paths] ? relative_to_base(path) : path)
242
+ insert_path(path)
242
243
  end
243
- insert_path(path)
244
244
  end
245
245
  end
246
246
  end
@@ -253,11 +253,11 @@ module Listen
253
253
  def content_modified?(path)
254
254
  sha1_checksum = Digest::SHA1.file(path).to_s
255
255
  return false if @sha1_checksums[path] == sha1_checksum
256
-
257
- had_no_checksum = @sha1_checksums[path].nil?
258
- @sha1_checksums[path] = sha1_checksum
259
-
260
- had_no_checksum ? false : true
256
+ @sha1_checksums.key?(path)
257
+ rescue Errno::EACCES, Errno::ENOENT
258
+ false
259
+ ensure
260
+ @sha1_checksums[path] = sha1_checksum if sha1_checksum
261
261
  end
262
262
 
263
263
  # Traverses the base directory looking for paths that should
@@ -292,6 +292,7 @@ module Listen
292
292
  meta_data.type = File.directory?(path) ? 'Dir' : 'File'
293
293
  meta_data.mtime = mtime_of(path) unless meta_data.type == 'Dir' # mtimes of dirs are not used yet
294
294
  @paths[File.dirname(path)][File.basename(path)] = meta_data
295
+ rescue Errno::ENOENT
295
296
  end
296
297
 
297
298
  # Returns whether or not a path exists in the paths hash.
@@ -311,7 +312,7 @@ module Listen
311
312
  # @return [Fixnum, Float] the mtime of the file
312
313
  #
313
314
  def mtime_of(file)
314
- File.mtime(file).send(HIGH_PRECISION_SUPPORTED ? :to_f : :to_i)
315
+ File.lstat(file).mtime.send(HIGH_PRECISION_SUPPORTED ? :to_f : :to_i)
315
316
  end
316
317
  end
317
318
  end
@@ -1,3 +1,3 @@
1
1
  module Listen
2
- VERSION = '0.4.2'
2
+ VERSION = '0.4.7'
3
3
  end
@@ -193,6 +193,25 @@ describe Listen::DirectoryRecord do
193
193
  it 'returns nil when the passed path is not inside the base-directory' do
194
194
  subject.relative_to_base('/tmp/some_random_path').should be_nil
195
195
  end
196
+
197
+ context 'when containing regexp characters in the base directory' do
198
+ before do
199
+ fixtures do |path|
200
+ mkdir 'a_directory$'
201
+ @dir = described_class.new(path + '/a_directory$')
202
+ @dir.build
203
+ end
204
+ end
205
+
206
+ it 'removes the path of the base-directory from the passed path' do
207
+ path = 'dir/to/app/file.rb'
208
+ @dir.relative_to_base(File.join(@dir.directory, path)).should eq path
209
+ end
210
+
211
+ it 'returns nil when the passed path is not inside the base-directory' do
212
+ @dir.relative_to_base('/tmp/some_random_path').should be_nil
213
+ end
214
+ end
196
215
  end
197
216
 
198
217
  describe '#fetch_changes' do
@@ -385,7 +404,7 @@ describe Listen::DirectoryRecord do
385
404
  end
386
405
  end
387
406
 
388
- context '#27 - when a file is created and then checked for modifications at the same second' do
407
+ context 'when a file is created and then checked for modifications at the same second - #27' do
389
408
  # This issue was the result of checking a file for content changes when
390
409
  # the mtime and the checking time are the same. In this case there
391
410
  # is no checksum saved, so the file was reported as being changed.
@@ -1030,5 +1049,90 @@ describe Listen::DirectoryRecord do
1030
1049
  end
1031
1050
  end
1032
1051
  end
1052
+
1053
+ context 'within a directory containing unreadble paths - #32' do
1054
+ it 'detects changes more than a second apart' do
1055
+ fixtures do |path|
1056
+ touch 'unreadable_file.txt'
1057
+ chmod 000, 'unreadable_file.txt'
1058
+
1059
+ modified, added, removed = changes(path) do
1060
+ sleep 1.1
1061
+ touch 'unreadable_file.txt'
1062
+ end
1063
+
1064
+ added.should be_empty
1065
+ modified.should =~ %w(unreadable_file.txt)
1066
+ removed.should be_empty
1067
+ end
1068
+ end
1069
+
1070
+ context 'with multiple changes within the same second' do
1071
+ before { ensure_same_second }
1072
+
1073
+ it 'does not detect changes even if content changes', :unless => described_class::HIGH_PRECISION_SUPPORTED do
1074
+ fixtures do |path|
1075
+ touch 'unreadable_file.txt'
1076
+
1077
+ modified, added, removed = changes(path) do
1078
+ open('unreadable_file.txt', 'w') { |f| f.write('foo') }
1079
+ chmod 000, 'unreadable_file.txt'
1080
+ end
1081
+
1082
+ added.should be_empty
1083
+ modified.should be_empty
1084
+ removed.should be_empty
1085
+ end
1086
+ end
1087
+ end
1088
+ end
1089
+
1090
+ context 'within a directory containing a removed file - #39' do
1091
+ it 'does not raise an exception when hashing a removed file' do
1092
+
1093
+ # simulate a race condition where the file is removed after the
1094
+ # change event is tracked, but before the hash is calculated
1095
+ Digest::SHA1.should_receive(:file).and_raise(Errno::ENOENT)
1096
+
1097
+ lambda {
1098
+ fixtures do |path|
1099
+ file = 'removed_file.txt'
1100
+ touch file
1101
+ changes(path) { touch file }
1102
+ end
1103
+ }.should_not raise_error(Errno::ENOENT)
1104
+ end
1105
+ end
1106
+
1107
+ context 'with symlinks' do
1108
+ it 'looks at symlinks not their targets' do
1109
+ fixtures do |path|
1110
+ touch 'target'
1111
+ symlink 'target', 'symlink'
1112
+
1113
+ record = described_class.new(path)
1114
+ record.build
1115
+
1116
+ sleep 1
1117
+ touch 'target'
1118
+
1119
+ record.fetch_changes([path], :relative_paths => true)[:modified].should == ['target']
1120
+ end
1121
+ end
1122
+
1123
+ it 'handles broken symlinks' do
1124
+ fixtures do |path|
1125
+ symlink 'target', 'symlink'
1126
+
1127
+ record = described_class.new(path)
1128
+ record.build
1129
+
1130
+ sleep 1
1131
+ rm 'symlink'
1132
+ symlink 'new-target', 'symlink'
1133
+ record.fetch_changes([path], :relative_paths => true)
1134
+ end
1135
+ end
1136
+ end
1033
1137
  end
1034
1138
  end
@@ -1,14 +1,16 @@
1
1
  require 'listen'
2
2
 
3
- ENV["TEST_LATENCY"] ||= "0.1"
3
+ ENV["TEST_LATENCY"] ||= "0.25"
4
4
 
5
5
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
6
6
 
7
7
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
8
8
  RSpec.configure do |config|
9
+ config.color_enabled = true
10
+ config.order = :random
11
+ config.filter_run :focus => true
9
12
  config.treat_symbols_as_metadata_keys_with_true_values = true
10
13
  config.run_all_when_everything_filtered = true
11
- config.filter_run :focus
12
14
  end
13
15
 
14
16
  def test_latency
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sass
3
3
  version: !ruby/object:Gem::Version
4
- hash: 592302343
4
+ hash: 592302399
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 3
8
8
  - 2
9
9
  - 0
10
10
  - alpha
11
- - 269
12
- version: 3.2.0.alpha.269
11
+ - 273
12
+ version: 3.2.0.alpha.273
13
13
  platform: ruby
14
14
  authors:
15
15
  - Nathan Weizenbaum
@@ -19,7 +19,7 @@ autorequire:
19
19
  bindir: bin
20
20
  cert_chain: []
21
21
 
22
- date: 2012-07-13 00:00:00 -04:00
22
+ date: 2012-07-20 00:00:00 -04:00
23
23
  default_executable:
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
@@ -110,10 +110,10 @@ files:
110
110
  - lib/sass/script/list.rb
111
111
  - lib/sass/script/literal.rb
112
112
  - lib/sass/script/node.rb
113
- - lib/sass/script/null.rb
114
113
  - lib/sass/script/number.rb
115
114
  - lib/sass/script/operation.rb
116
115
  - lib/sass/script/parser.rb
116
+ - lib/sass/script/null.rb
117
117
  - lib/sass/script/string.rb
118
118
  - lib/sass/script/string_interpolation.rb
119
119
  - lib/sass/script/unary_operation.rb
@@ -154,6 +154,7 @@ files:
154
154
  - lib/sass/tree/content_node.rb
155
155
  - lib/sass/tree/css_import_node.rb
156
156
  - lib/sass/tree/variable_node.rb
157
+ - lib/sass/tree/warn_node.rb
157
158
  - lib/sass/tree/visitors/base.rb
158
159
  - lib/sass/tree/visitors/check_nesting.rb
159
160
  - lib/sass/tree/visitors/convert.rb
@@ -163,7 +164,6 @@ files:
163
164
  - lib/sass/tree/visitors/perform.rb
164
165
  - lib/sass/tree/visitors/set_options.rb
165
166
  - lib/sass/tree/visitors/to_css.rb
166
- - lib/sass/tree/warn_node.rb
167
167
  - lib/sass/tree/while_node.rb
168
168
  - lib/sass/tree/supports_node.rb
169
169
  - lib/sass/tree/trace_node.rb
@@ -275,7 +275,6 @@ files:
275
275
  - test/sass/templates/bork2.sass
276
276
  - test/sass/templates/bork3.sass
277
277
  - test/sass/templates/bork4.sass
278
- - test/sass/templates/bork5.sass
279
278
  - test/sass/templates/compact.sass
280
279
  - test/sass/templates/complex.sass
281
280
  - test/sass/templates/compressed.sass
@@ -298,7 +297,6 @@ files:
298
297
  - test/sass/templates/nested_bork2.sass
299
298
  - test/sass/templates/nested_bork3.sass
300
299
  - test/sass/templates/nested_bork4.sass
301
- - test/sass/templates/nested_bork5.sass
302
300
  - test/sass/templates/nested_import.sass
303
301
  - test/sass/templates/nested_mixin_bork.sass
304
302
  - test/sass/templates/options.sass
@@ -1,3 +0,0 @@
1
- foo
2
- @function bar($a)
3
- @return $a
@@ -1,2 +0,0 @@
1
-
2
- @import bork5