haml 3.1.0.alpha.14 → 3.1.0.alpha.17

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

Files changed (222) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/VERSION +1 -1
  3. data/lib/haml.rb +3 -2
  4. data/lib/haml/exec.rb +0 -226
  5. data/lib/sass.rb +8 -0
  6. data/lib/sass/plugin.rb +8 -0
  7. data/lib/sass/rails2_shim.rb +9 -0
  8. data/lib/sass/rails3_shim.rb +16 -0
  9. data/vendor/sass/CONTRIBUTING +3 -0
  10. data/vendor/sass/MIT-LICENSE +20 -0
  11. data/vendor/sass/README.md +201 -0
  12. data/vendor/sass/Rakefile +363 -0
  13. data/vendor/sass/TODO +39 -0
  14. data/vendor/sass/VERSION +1 -0
  15. data/vendor/sass/VERSION_NAME +1 -0
  16. data/vendor/sass/bin/css2sass +13 -0
  17. data/vendor/sass/bin/sass +8 -0
  18. data/vendor/sass/bin/sass-convert +7 -0
  19. data/vendor/sass/doc-src/FAQ.md +35 -0
  20. data/vendor/sass/doc-src/INDENTED_SYNTAX.md +210 -0
  21. data/vendor/sass/doc-src/SASS_CHANGELOG.md +1878 -0
  22. data/vendor/sass/doc-src/SASS_REFERENCE.md +1713 -0
  23. data/vendor/sass/doc-src/SCSS_FOR_SASS_USERS.md +155 -0
  24. data/vendor/sass/ext/extconf.rb +10 -0
  25. data/vendor/sass/extra/update_watch.rb +13 -0
  26. data/vendor/sass/init.rb +18 -0
  27. data/vendor/sass/lib/sass.rb +71 -0
  28. data/vendor/sass/lib/sass/cache_store.rb +208 -0
  29. data/vendor/sass/lib/sass/callbacks.rb +66 -0
  30. data/vendor/sass/lib/sass/css.rb +294 -0
  31. data/vendor/sass/lib/sass/engine.rb +792 -0
  32. data/vendor/sass/lib/sass/environment.rb +143 -0
  33. data/vendor/sass/lib/sass/error.rb +201 -0
  34. data/vendor/sass/lib/sass/exec.rb +619 -0
  35. data/vendor/sass/lib/sass/importers.rb +22 -0
  36. data/vendor/sass/lib/sass/importers/base.rb +138 -0
  37. data/vendor/sass/lib/sass/importers/filesystem.rb +121 -0
  38. data/vendor/sass/lib/sass/less.rb +363 -0
  39. data/vendor/sass/lib/sass/plugin.rb +126 -0
  40. data/vendor/sass/lib/sass/plugin/compiler.rb +346 -0
  41. data/vendor/sass/lib/sass/plugin/configuration.rb +123 -0
  42. data/vendor/sass/lib/sass/plugin/generic.rb +15 -0
  43. data/vendor/sass/lib/sass/plugin/merb.rb +48 -0
  44. data/vendor/sass/lib/sass/plugin/rack.rb +47 -0
  45. data/vendor/sass/lib/sass/plugin/rails.rb +41 -0
  46. data/vendor/sass/lib/sass/plugin/staleness_checker.rb +145 -0
  47. data/vendor/sass/lib/sass/railtie.rb +8 -0
  48. data/vendor/sass/lib/sass/repl.rb +58 -0
  49. data/vendor/sass/lib/sass/root.rb +7 -0
  50. data/vendor/sass/lib/sass/script.rb +63 -0
  51. data/vendor/sass/lib/sass/script/bool.rb +18 -0
  52. data/vendor/sass/lib/sass/script/color.rb +491 -0
  53. data/vendor/sass/lib/sass/script/css_lexer.rb +29 -0
  54. data/vendor/sass/lib/sass/script/css_parser.rb +31 -0
  55. data/vendor/sass/lib/sass/script/funcall.rb +76 -0
  56. data/vendor/sass/lib/sass/script/functions.rb +852 -0
  57. data/vendor/sass/lib/sass/script/interpolation.rb +70 -0
  58. data/vendor/sass/lib/sass/script/lexer.rb +337 -0
  59. data/vendor/sass/lib/sass/script/literal.rb +236 -0
  60. data/vendor/sass/lib/sass/script/node.rb +112 -0
  61. data/vendor/sass/lib/sass/script/number.rb +423 -0
  62. data/vendor/sass/lib/sass/script/operation.rb +90 -0
  63. data/vendor/sass/lib/sass/script/parser.rb +392 -0
  64. data/vendor/sass/lib/sass/script/string.rb +67 -0
  65. data/vendor/sass/lib/sass/script/string_interpolation.rb +93 -0
  66. data/vendor/sass/lib/sass/script/unary_operation.rb +57 -0
  67. data/vendor/sass/lib/sass/script/variable.rb +48 -0
  68. data/vendor/sass/lib/sass/scss.rb +17 -0
  69. data/vendor/sass/lib/sass/scss/css_parser.rb +51 -0
  70. data/vendor/sass/lib/sass/scss/parser.rb +838 -0
  71. data/vendor/sass/lib/sass/scss/rx.rb +126 -0
  72. data/vendor/sass/lib/sass/scss/sass_parser.rb +11 -0
  73. data/vendor/sass/lib/sass/scss/script_lexer.rb +15 -0
  74. data/vendor/sass/lib/sass/scss/script_parser.rb +25 -0
  75. data/vendor/sass/lib/sass/scss/static_parser.rb +40 -0
  76. data/vendor/sass/lib/sass/selector.rb +361 -0
  77. data/vendor/sass/lib/sass/selector/abstract_sequence.rb +62 -0
  78. data/vendor/sass/lib/sass/selector/comma_sequence.rb +82 -0
  79. data/vendor/sass/lib/sass/selector/sequence.rb +236 -0
  80. data/vendor/sass/lib/sass/selector/simple.rb +113 -0
  81. data/vendor/sass/lib/sass/selector/simple_sequence.rb +135 -0
  82. data/vendor/sass/lib/sass/shared.rb +78 -0
  83. data/vendor/sass/lib/sass/tree/comment_node.rb +128 -0
  84. data/vendor/sass/lib/sass/tree/debug_node.rb +36 -0
  85. data/vendor/sass/lib/sass/tree/directive_node.rb +75 -0
  86. data/vendor/sass/lib/sass/tree/extend_node.rb +65 -0
  87. data/vendor/sass/lib/sass/tree/for_node.rb +67 -0
  88. data/vendor/sass/lib/sass/tree/if_node.rb +81 -0
  89. data/vendor/sass/lib/sass/tree/import_node.rb +124 -0
  90. data/vendor/sass/lib/sass/tree/mixin_def_node.rb +60 -0
  91. data/vendor/sass/lib/sass/tree/mixin_node.rb +123 -0
  92. data/vendor/sass/lib/sass/tree/node.rb +490 -0
  93. data/vendor/sass/lib/sass/tree/prop_node.rb +220 -0
  94. data/vendor/sass/lib/sass/tree/root_node.rb +125 -0
  95. data/vendor/sass/lib/sass/tree/rule_node.rb +273 -0
  96. data/vendor/sass/lib/sass/tree/variable_node.rb +39 -0
  97. data/vendor/sass/lib/sass/tree/warn_node.rb +42 -0
  98. data/vendor/sass/lib/sass/tree/while_node.rb +48 -0
  99. data/vendor/sass/lib/sass/util.rb +700 -0
  100. data/vendor/sass/lib/sass/util/subset_map.rb +101 -0
  101. data/vendor/sass/lib/sass/version.rb +109 -0
  102. data/vendor/sass/rails/init.rb +1 -0
  103. data/vendor/sass/sass.gemspec +32 -0
  104. data/vendor/sass/test/sass/cache_test.rb +74 -0
  105. data/vendor/sass/test/sass/callbacks_test.rb +61 -0
  106. data/vendor/sass/test/sass/conversion_test.rb +1210 -0
  107. data/vendor/sass/test/sass/css2sass_test.rb +364 -0
  108. data/vendor/sass/test/sass/data/hsl-rgb.txt +319 -0
  109. data/vendor/sass/test/sass/engine_test.rb +2305 -0
  110. data/vendor/sass/test/sass/extend_test.rb +1348 -0
  111. data/vendor/sass/test/sass/functions_test.rb +565 -0
  112. data/vendor/sass/test/sass/importer_test.rb +104 -0
  113. data/vendor/sass/test/sass/less_conversion_test.rb +632 -0
  114. data/vendor/sass/test/sass/mock_importer.rb +49 -0
  115. data/vendor/sass/test/sass/more_results/more1.css +9 -0
  116. data/vendor/sass/test/sass/more_results/more1_with_line_comments.css +26 -0
  117. data/vendor/sass/test/sass/more_results/more_import.css +29 -0
  118. data/vendor/sass/test/sass/more_templates/_more_partial.sass +2 -0
  119. data/vendor/sass/test/sass/more_templates/more1.sass +23 -0
  120. data/vendor/sass/test/sass/more_templates/more_import.sass +11 -0
  121. data/vendor/sass/test/sass/plugin_test.rb +430 -0
  122. data/vendor/sass/test/sass/results/alt.css +4 -0
  123. data/vendor/sass/test/sass/results/basic.css +9 -0
  124. data/vendor/sass/test/sass/results/compact.css +5 -0
  125. data/vendor/sass/test/sass/results/complex.css +86 -0
  126. data/vendor/sass/test/sass/results/compressed.css +1 -0
  127. data/vendor/sass/test/sass/results/expanded.css +19 -0
  128. data/vendor/sass/test/sass/results/import.css +31 -0
  129. data/vendor/sass/test/sass/results/line_numbers.css +49 -0
  130. data/vendor/sass/test/sass/results/mixins.css +95 -0
  131. data/vendor/sass/test/sass/results/multiline.css +24 -0
  132. data/vendor/sass/test/sass/results/nested.css +22 -0
  133. data/vendor/sass/test/sass/results/options.css +1 -0
  134. data/vendor/sass/test/sass/results/parent_ref.css +13 -0
  135. data/vendor/sass/test/sass/results/script.css +16 -0
  136. data/vendor/sass/test/sass/results/scss_import.css +31 -0
  137. data/vendor/sass/test/sass/results/scss_importee.css +2 -0
  138. data/vendor/sass/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  139. data/vendor/sass/test/sass/results/subdir/subdir.css +3 -0
  140. data/vendor/sass/test/sass/results/units.css +11 -0
  141. data/vendor/sass/test/sass/results/warn.css +0 -0
  142. data/vendor/sass/test/sass/results/warn_imported.css +0 -0
  143. data/vendor/sass/test/sass/script_conversion_test.rb +254 -0
  144. data/vendor/sass/test/sass/script_test.rb +470 -0
  145. data/vendor/sass/test/sass/scss/css_test.rb +897 -0
  146. data/vendor/sass/test/sass/scss/rx_test.rb +156 -0
  147. data/vendor/sass/test/sass/scss/scss_test.rb +1088 -0
  148. data/vendor/sass/test/sass/scss/test_helper.rb +37 -0
  149. data/vendor/sass/test/sass/templates/_partial.sass +2 -0
  150. data/vendor/sass/test/sass/templates/alt.sass +16 -0
  151. data/vendor/sass/test/sass/templates/basic.sass +23 -0
  152. data/vendor/sass/test/sass/templates/bork1.sass +2 -0
  153. data/vendor/sass/test/sass/templates/bork2.sass +2 -0
  154. data/vendor/sass/test/sass/templates/bork3.sass +2 -0
  155. data/vendor/sass/test/sass/templates/bork4.sass +2 -0
  156. data/vendor/sass/test/sass/templates/compact.sass +17 -0
  157. data/vendor/sass/test/sass/templates/complex.sass +305 -0
  158. data/vendor/sass/test/sass/templates/compressed.sass +15 -0
  159. data/vendor/sass/test/sass/templates/expanded.sass +17 -0
  160. data/vendor/sass/test/sass/templates/import.sass +12 -0
  161. data/vendor/sass/test/sass/templates/importee.less +2 -0
  162. data/vendor/sass/test/sass/templates/importee.sass +19 -0
  163. data/vendor/sass/test/sass/templates/line_numbers.sass +13 -0
  164. data/vendor/sass/test/sass/templates/mixin_bork.sass +5 -0
  165. data/vendor/sass/test/sass/templates/mixins.sass +76 -0
  166. data/vendor/sass/test/sass/templates/multiline.sass +20 -0
  167. data/vendor/sass/test/sass/templates/nested.sass +25 -0
  168. data/vendor/sass/test/sass/templates/nested_bork1.sass +2 -0
  169. data/vendor/sass/test/sass/templates/nested_bork2.sass +2 -0
  170. data/vendor/sass/test/sass/templates/nested_bork3.sass +2 -0
  171. data/vendor/sass/test/sass/templates/nested_bork4.sass +2 -0
  172. data/vendor/sass/test/sass/templates/nested_mixin_bork.sass +6 -0
  173. data/vendor/sass/test/sass/templates/options.sass +2 -0
  174. data/vendor/sass/test/sass/templates/parent_ref.sass +25 -0
  175. data/vendor/sass/test/sass/templates/script.sass +101 -0
  176. data/vendor/sass/test/sass/templates/scss_import.scss +11 -0
  177. data/vendor/sass/test/sass/templates/scss_importee.scss +1 -0
  178. data/vendor/sass/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  179. data/vendor/sass/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  180. data/vendor/sass/test/sass/templates/subdir/subdir.sass +6 -0
  181. data/vendor/sass/test/sass/templates/units.sass +11 -0
  182. data/vendor/sass/test/sass/templates/warn.sass +3 -0
  183. data/vendor/sass/test/sass/templates/warn_imported.sass +4 -0
  184. data/vendor/sass/test/sass/test_helper.rb +8 -0
  185. data/vendor/sass/test/sass/util/subset_map_test.rb +91 -0
  186. data/vendor/sass/test/sass/util_test.rb +275 -0
  187. data/vendor/sass/test/test_helper.rb +64 -0
  188. data/vendor/sass/vendor/fssm/LICENSE +20 -0
  189. data/vendor/sass/vendor/fssm/README.markdown +55 -0
  190. data/vendor/sass/vendor/fssm/Rakefile +59 -0
  191. data/vendor/sass/vendor/fssm/VERSION.yml +5 -0
  192. data/vendor/sass/vendor/fssm/example.rb +9 -0
  193. data/vendor/sass/vendor/fssm/fssm.gemspec +77 -0
  194. data/vendor/sass/vendor/fssm/lib/fssm.rb +33 -0
  195. data/vendor/sass/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  196. data/vendor/sass/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  197. data/vendor/sass/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  198. data/vendor/sass/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  199. data/vendor/sass/vendor/fssm/lib/fssm/monitor.rb +26 -0
  200. data/vendor/sass/vendor/fssm/lib/fssm/path.rb +91 -0
  201. data/vendor/sass/vendor/fssm/lib/fssm/pathname.rb +502 -0
  202. data/vendor/sass/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  203. data/vendor/sass/vendor/fssm/lib/fssm/state/file.rb +24 -0
  204. data/vendor/sass/vendor/fssm/lib/fssm/support.rb +63 -0
  205. data/vendor/sass/vendor/fssm/lib/fssm/tree.rb +176 -0
  206. data/vendor/sass/vendor/fssm/profile/prof-cache.rb +40 -0
  207. data/vendor/sass/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  208. data/vendor/sass/vendor/fssm/profile/prof-pathname.rb +68 -0
  209. data/vendor/sass/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  210. data/vendor/sass/vendor/fssm/profile/prof.html +2379 -0
  211. data/vendor/sass/vendor/fssm/spec/path_spec.rb +75 -0
  212. data/vendor/sass/vendor/fssm/spec/root/duck/quack.txt +0 -0
  213. data/vendor/sass/vendor/fssm/spec/root/file.css +0 -0
  214. data/vendor/sass/vendor/fssm/spec/root/file.rb +0 -0
  215. data/vendor/sass/vendor/fssm/spec/root/file.yml +0 -0
  216. data/vendor/sass/vendor/fssm/spec/root/moo/cow.txt +0 -0
  217. data/vendor/sass/vendor/fssm/spec/spec_helper.rb +14 -0
  218. data/vendor/sass/yard/callbacks.rb +29 -0
  219. data/vendor/sass/yard/default/fulldoc/html/css/common.sass +26 -0
  220. data/vendor/sass/yard/default/layout/html/footer.erb +12 -0
  221. data/vendor/sass/yard/inherited_hash.rb +41 -0
  222. metadata +219 -2
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 4
5
+ :build:
@@ -0,0 +1,9 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+ require 'fssm'
4
+
5
+ FSSM.monitor('.', '**/*') do
6
+ update {|b, r| puts "Update in #{b} to #{r}"}
7
+ delete {|b, r| puts "Delete in #{b} to #{r}"}
8
+ create {|b, r| puts "Create in #{b} to #{r}"}
9
+ end
@@ -0,0 +1,77 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{fssm}
8
+ s.version = "0.1.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Travis Tilley"]
12
+ s.date = %q{2010-03-10}
13
+ s.description = %q{file system state monitor}
14
+ s.email = %q{ttilley@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.markdown",
24
+ "Rakefile",
25
+ "VERSION.yml",
26
+ "example.rb",
27
+ "fssm.gemspec",
28
+ "lib/fssm.rb",
29
+ "lib/fssm/backends/fsevents.rb",
30
+ "lib/fssm/backends/inotify.rb",
31
+ "lib/fssm/backends/polling.rb",
32
+ "lib/fssm/backends/rubycocoa/fsevents.rb",
33
+ "lib/fssm/monitor.rb",
34
+ "lib/fssm/path.rb",
35
+ "lib/fssm/pathname.rb",
36
+ "lib/fssm/state/directory.rb",
37
+ "lib/fssm/state/file.rb",
38
+ "lib/fssm/support.rb",
39
+ "lib/fssm/tree.rb",
40
+ "profile/prof-cache.rb",
41
+ "profile/prof-fssm-pathname.html",
42
+ "profile/prof-pathname.rb",
43
+ "profile/prof-plain-pathname.html",
44
+ "profile/prof.html",
45
+ "spec/path_spec.rb",
46
+ "spec/root/duck/quack.txt",
47
+ "spec/root/file.css",
48
+ "spec/root/file.rb",
49
+ "spec/root/file.yml",
50
+ "spec/root/moo/cow.txt",
51
+ "spec/spec_helper.rb"
52
+ ]
53
+ s.homepage = %q{http://github.com/ttilley/fssm}
54
+ s.rdoc_options = ["--charset=UTF-8"]
55
+ s.require_paths = ["lib"]
56
+ s.rubygems_version = %q{1.3.6}
57
+ s.summary = %q{file system state monitor}
58
+ s.test_files = [
59
+ "spec/path_spec.rb",
60
+ "spec/spec_helper.rb",
61
+ "spec/root/file.rb"
62
+ ]
63
+
64
+ if s.respond_to? :specification_version then
65
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
66
+ s.specification_version = 3
67
+
68
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
69
+ s.add_development_dependency(%q<rspec>, [">= 0"])
70
+ else
71
+ s.add_dependency(%q<rspec>, [">= 0"])
72
+ end
73
+ else
74
+ s.add_dependency(%q<rspec>, [">= 0"])
75
+ end
76
+ end
77
+
@@ -0,0 +1,33 @@
1
+ dir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
3
+
4
+ module FSSM
5
+ FileNotFoundError = Class.new(StandardError)
6
+ CallbackError = Class.new(StandardError)
7
+
8
+ class << self
9
+ def dbg(msg=nil)
10
+ STDERR.puts(msg)
11
+ end
12
+
13
+ def monitor(*args, &block)
14
+ monitor = FSSM::Monitor.new
15
+ FSSM::Support.use_block(args.empty? ? monitor : monitor.path(*args), block)
16
+
17
+ monitor.run
18
+ end
19
+ end
20
+ end
21
+
22
+ require 'thread'
23
+
24
+ require 'fssm/pathname'
25
+ require 'fssm/support'
26
+ require 'fssm/tree'
27
+ require 'fssm/path'
28
+ require 'fssm/state/directory'
29
+ require 'fssm/state/file'
30
+ require 'fssm/monitor'
31
+
32
+ require "fssm/backends/#{FSSM::Support.backend.downcase}"
33
+ FSSM::Backends::Default = FSSM::Backends.const_get(FSSM::Support.backend)
@@ -0,0 +1,36 @@
1
+ require File.join(File.dirname(__FILE__), 'rubycocoa/fsevents')
2
+
3
+ module FSSM::Backends
4
+ class FSEvents
5
+ def initialize
6
+ @handlers = {}
7
+ @fsevents = []
8
+ end
9
+
10
+ def add_handler(handler, preload=true)
11
+ @handlers[handler.path.to_s] = handler
12
+
13
+ fsevent = Rucola::FSEvents.new(handler.path.to_s, {:latency => 0.5}) do |events|
14
+ events.each do |event|
15
+ handler.refresh(event.path)
16
+ end
17
+ end
18
+
19
+ fsevent.create_stream
20
+ handler.refresh(nil, true) if preload
21
+ fsevent.start
22
+ @fsevents << fsevent
23
+ end
24
+
25
+ def run
26
+ begin
27
+ OSX.CFRunLoopRun
28
+ rescue Interrupt
29
+ @fsevents.each do |fsev|
30
+ fsev.stop
31
+ end
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ module FSSM::Backends
2
+ class Inotify
3
+ def initialize
4
+ @notifier = INotify::Notifier.new
5
+ end
6
+
7
+ def add_handler(handler, preload=true)
8
+ @notifier.watch(handler.path.to_s, :recursive, :attrib, :modify, :create,
9
+ :delete, :delete_self, :moved_from, :moved_to, :move_self) do |event|
10
+ path = FSSM::Pathname.for(event.absolute_name)
11
+ path = path.dirname unless event.name == "" # Event on root directory
12
+ handler.refresh(path)
13
+ end
14
+
15
+ handler.refresh(nil, true) if preload
16
+ end
17
+
18
+ def run
19
+ begin
20
+ @notifier.run
21
+ rescue Interrupt
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module FSSM::Backends
2
+ class Polling
3
+ def initialize(options={})
4
+ @handlers = []
5
+ @latency = options[:latency] || 1.5
6
+ end
7
+
8
+ def add_handler(handler, preload=true)
9
+ handler.refresh(nil, true) if preload
10
+ @handlers << handler
11
+ end
12
+
13
+ def run
14
+ begin
15
+ loop do
16
+ start = Time.now.to_f
17
+ @handlers.each {|handler| handler.refresh}
18
+ nap_time = @latency - (Time.now.to_f - start)
19
+ sleep nap_time if nap_time > 0
20
+ end
21
+ rescue Interrupt
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,131 @@
1
+ OSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework'
2
+
3
+ module Rucola
4
+ class FSEvents
5
+ class FSEvent
6
+ attr_reader :fsevents_object
7
+ attr_reader :id
8
+ attr_reader :path
9
+
10
+ def initialize(fsevents_object, id, path)
11
+ @fsevents_object, @id, @path = fsevents_object, id, path
12
+ end
13
+
14
+ # Returns an array of the files/dirs in the path that the event occurred in.
15
+ # The files are sorted by the modification time, the first entry is the last modified file.
16
+ def files
17
+ Dir.glob("#{File.expand_path(path)}/*").sort_by {|f| File.mtime(f) }.reverse
18
+ end
19
+
20
+ # Returns the last modified file in the path that the event occurred in.
21
+ def last_modified_file
22
+ files.first
23
+ end
24
+ end
25
+
26
+ class StreamError < StandardError;
27
+ end
28
+
29
+ attr_reader :paths
30
+ attr_reader :stream
31
+
32
+ attr_accessor :allocator
33
+ attr_accessor :context
34
+ attr_accessor :since
35
+ attr_accessor :latency
36
+ attr_accessor :flags
37
+
38
+ # Initializes a new FSEvents `watchdog` object and starts watching the directories you specify for events. The
39
+ # block is used as a handler for events, which are passed as the block's argument. This method is the easiest
40
+ # way to start watching some directories if you don't care about the details of setting up the event stream.
41
+ #
42
+ # Rucola::FSEvents.start_watching('/tmp') do |events|
43
+ # events.each { |event| log.debug("#{event.files.inspect} were changed.") }
44
+ # end
45
+ #
46
+ # Rucola::FSEvents.start_watching('/var/log/system.log', '/var/log/secure.log', :since => last_id, :latency => 5) do
47
+ # Growl.notify("Something was added to your log files!")
48
+ # end
49
+ #
50
+ # Note that the method also returns the FSEvents object. This enables you to control the event stream if you want to.
51
+ #
52
+ # fsevents = Rucola::FSEvents.start_watching('/Volumes') do |events|
53
+ # events.each { |event| Growl.notify("Volume changes: #{event.files.to_sentence}") }
54
+ # end
55
+ # fsevents.stop
56
+ def self.start_watching(*params, &block)
57
+ fsevents = new(*params, &block)
58
+ fsevents.create_stream
59
+ fsevents.start
60
+ fsevents
61
+ end
62
+
63
+ # Creates a new FSEvents `watchdog` object. You can specify a list of paths to watch and options to control the
64
+ # behaviour of the watchdog. The block you pass serves as a callback when an event is generated on one of the
65
+ # specified paths.
66
+ #
67
+ # fsevents = FSEvents.new('/etc/passwd') { Mailer.send_mail("Someone touched the password file!") }
68
+ # fsevents.create_stream
69
+ # fsevents.start
70
+ #
71
+ # fsevents = FSEvents.new('/home/upload', :since => UploadWatcher.last_event_id) do |events|
72
+ # events.each do |event|
73
+ # UploadWatcher.last_event_id = event.id
74
+ # event.files.each do |file|
75
+ # UploadWatcher.logfile.append("#{file} was changed")
76
+ # end
77
+ # end
78
+ # end
79
+ #
80
+ # *:since: The service will report events that have happened after the supplied event ID. Never use 0 because that
81
+ # will cause every fsevent since the "beginning of time" to be reported. Use OSX::KFSEventStreamEventIdSinceNow
82
+ # if you want to receive events that have happened after this call. (Default: OSX::KFSEventStreamEventIdSinceNow).
83
+ # You can find the ID's passed with :since in the events passed to your block.
84
+ # *:latency: Number of seconds to wait until an FSEvent is reported, this allows the service to bundle events. (Default: 0.0)
85
+ #
86
+ # Please refer to the Cocoa documentation for the rest of the options.
87
+ def initialize(*params, &block)
88
+ raise ArgumentError, 'No callback block was specified.' unless block_given?
89
+
90
+ options = params.last.kind_of?(Hash) ? params.pop : {}
91
+ @paths = params.flatten
92
+
93
+ paths.each { |path| raise ArgumentError, "The specified path (#{path}) does not exist." unless File.exist?(path) }
94
+
95
+ @allocator = options[:allocator] || OSX::KCFAllocatorDefault
96
+ @context = options[:context] || nil
97
+ @since = options[:since] || OSX::KFSEventStreamEventIdSinceNow
98
+ @latency = options[:latency] || 0.0
99
+ @flags = options[:flags] || 0
100
+ @stream = options[:stream] || nil
101
+
102
+ @user_callback = block
103
+ @callback = Proc.new do |stream, client_callback_info, number_of_events, paths_pointer, event_flags, event_ids|
104
+ paths_pointer.regard_as('*')
105
+ events = []
106
+ number_of_events.times {|i| events << Rucola::FSEvents::FSEvent.new(self, event_ids[i], paths_pointer[i]) }
107
+ @user_callback.call(events)
108
+ end
109
+ end
110
+
111
+ # Create the stream.
112
+ # Raises a Rucola::FSEvents::StreamError if the stream could not be created.
113
+ def create_stream
114
+ @stream = OSX.FSEventStreamCreate(@allocator, @callback, @context, @paths, @since, @latency, @flags)
115
+ raise(StreamError, 'Unable to create FSEvents stream.') unless @stream
116
+ OSX.FSEventStreamScheduleWithRunLoop(@stream, OSX.CFRunLoopGetCurrent, OSX::KCFRunLoopDefaultMode)
117
+ end
118
+
119
+ # Start the stream.
120
+ # Raises a Rucola::FSEvents::StreamError if the stream could not be started.
121
+ def start
122
+ raise(StreamError, 'Unable to start FSEvents stream.') unless OSX.FSEventStreamStart(@stream)
123
+ end
124
+
125
+ # Stop the stream.
126
+ # You can resume it by calling `start` again.
127
+ def stop
128
+ OSX.FSEventStreamStop(@stream)
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,26 @@
1
+ class FSSM::Monitor
2
+ def initialize(options={})
3
+ @options = options
4
+ @backend = FSSM::Backends::Default.new
5
+ end
6
+
7
+ def path(*args, &block)
8
+ path = FSSM::Path.new(*args)
9
+ FSSM::Support.use_block(path, block)
10
+
11
+ @backend.add_handler(FSSM::State::Directory.new(path))
12
+ path
13
+ end
14
+
15
+ def file(*args, &block)
16
+ path = FSSM::Path.new(*args)
17
+ FSSM::Support.use_block(path, block)
18
+
19
+ @backend.add_handler(FSSM::State::File.new(path))
20
+ path
21
+ end
22
+
23
+ def run
24
+ @backend.run
25
+ end
26
+ end
@@ -0,0 +1,91 @@
1
+ class FSSM::Path
2
+ def initialize(path=nil, glob=nil, &block)
3
+ set_path(path || '.')
4
+ set_glob(glob || '**/*')
5
+ init_callbacks
6
+
7
+ if block_given?
8
+ if block.arity == 1
9
+ block.call(self)
10
+ else
11
+ self.instance_eval(&block)
12
+ end
13
+ end
14
+ end
15
+
16
+ def to_s
17
+ @path.to_s
18
+ end
19
+
20
+ def to_pathname
21
+ @path
22
+ end
23
+
24
+ def glob(value=nil)
25
+ return @glob if value.nil?
26
+ set_glob(value)
27
+ end
28
+
29
+ def create(callback_or_path=nil, &block)
30
+ callback_action(:create, (block_given? ? block : callback_or_path))
31
+ end
32
+
33
+ def update(callback_or_path=nil, &block)
34
+ callback_action(:update, (block_given? ? block : callback_or_path))
35
+ end
36
+
37
+ def delete(callback_or_path=nil, &block)
38
+ callback_action(:delete, (block_given? ? block : callback_or_path))
39
+ end
40
+
41
+ private
42
+
43
+ def init_callbacks
44
+ do_nothing = lambda {|base, relative|}
45
+ @callbacks = Hash.new(do_nothing)
46
+ end
47
+
48
+ def callback_action(type, arg=nil)
49
+ if arg.is_a?(Proc)
50
+ set_callback(type, arg)
51
+ elsif arg.nil?
52
+ get_callback(type)
53
+ else
54
+ run_callback(type, arg)
55
+ end
56
+ end
57
+
58
+ def set_callback(type, arg)
59
+ raise ArgumentError, "Proc expected" unless arg.is_a?(Proc)
60
+ @callbacks[type] = arg
61
+ end
62
+
63
+ def get_callback(type)
64
+ @callbacks[type]
65
+ end
66
+
67
+ def run_callback(type, arg)
68
+ base, relative = split_path(arg)
69
+
70
+ begin
71
+ @callbacks[type].call(base, relative)
72
+ rescue Exception => e
73
+ raise FSSM::CallbackError, "#{type} - #{base.join(relative)}: #{e.message}", e.backtrace
74
+ end
75
+ end
76
+
77
+ def split_path(path)
78
+ path = FSSM::Pathname.for(path)
79
+ [@path, (path.relative? ? path : path.relative_path_from(@path))]
80
+ end
81
+
82
+ def set_path(path)
83
+ path = FSSM::Pathname.for(path)
84
+ raise FSSM::FileNotFoundError, "No such file or directory - #{path}" unless path.exist?
85
+ @path = path.expand_path
86
+ end
87
+
88
+ def set_glob(glob)
89
+ @glob = glob.is_a?(Array) ? glob : [glob]
90
+ end
91
+ end