compass-edge 0.9.4 → 0.9.5.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.
Files changed (187) hide show
  1. data/CHANGELOG.markdown +32 -2
  2. data/README.markdown +12 -2
  3. data/REVISION +1 -1
  4. data/Rakefile +3 -1
  5. data/VERSION.yml +1 -2
  6. data/examples/blueprint_default/index.html.haml +3 -3
  7. data/examples/blueprint_default/parts/forms.html.haml +2 -0
  8. data/examples/blueprint_default/src/screen.sass +1 -1
  9. data/examples/blueprint_plugins/index.html.haml +6 -6
  10. data/examples/blueprint_plugins/src/buttons.sass +2 -2
  11. data/examples/blueprint_plugins/src/link_icons.sass +1 -1
  12. data/examples/blueprint_plugins/src/rtl_screen.sass +3 -3
  13. data/examples/blueprint_plugins/src/screen.sass +2 -2
  14. data/examples/blueprint_semantic/src/liquid.sass +4 -4
  15. data/examples/blueprint_semantic/src/screen.sass +3 -3
  16. data/examples/compass/bootstrap.rb +3 -0
  17. data/examples/compass/extensions/yui/stylesheets/_yui.sass +7 -0
  18. data/examples/compass/extensions/yui/stylesheets/yui/modules/_base.sass +70 -0
  19. data/examples/compass/extensions/yui/stylesheets/yui/modules/_fonts.sass +45 -0
  20. data/examples/compass/extensions/yui/stylesheets/yui/modules/_grids.sass +385 -0
  21. data/examples/compass/extensions/yui/stylesheets/yui/modules/_reset.sass +61 -0
  22. data/examples/compass/extensions/yui/templates/project/manifest.rb +1 -0
  23. data/examples/compass/extensions/yui/templates/project/screen.sass +4 -0
  24. data/examples/compass/src/utilities.sass +2 -2
  25. data/examples/css3/config.rb +6 -0
  26. data/examples/css3/extensions/fancy-fonts/templates/project/Vtks Revolt.ttf +0 -0
  27. data/examples/css3/extensions/fancy-fonts/templates/project/angelina.ttf +0 -0
  28. data/examples/css3/extensions/fancy-fonts/templates/project/fancy-fonts.sass +7 -0
  29. data/examples/css3/extensions/fancy-fonts/templates/project/manifest.rb +5 -0
  30. data/examples/css3/images/fresh-peas.jpg +0 -0
  31. data/examples/css3/index.html.haml +55 -0
  32. data/examples/css3/src/_base.sass +14 -0
  33. data/examples/css3/src/fancy-fonts.sass +7 -0
  34. data/examples/css3/src/gradient.sass +10 -0
  35. data/examples/css3/src/main.sass +80 -0
  36. data/examples/css3/stylesheets/fonts/Vtks Revolt.ttf +0 -0
  37. data/examples/css3/stylesheets/fonts/angelina.ttf +0 -0
  38. data/examples/downloader.rb +2 -2
  39. data/examples/ninesixty/extensions/ninesixty/README.mkdn +56 -0
  40. data/examples/ninesixty/extensions/ninesixty/compass-960-plugin.gemspec +36 -0
  41. data/examples/ninesixty/extensions/ninesixty/lib/ninesixty.rb +1 -0
  42. data/examples/ninesixty/extensions/ninesixty/lib/ninesixty/compass_plugin.rb +5 -0
  43. data/examples/ninesixty/extensions/ninesixty/sass/960/_grid.sass +64 -0
  44. data/examples/ninesixty/extensions/ninesixty/sass/960/_text.sass +59 -0
  45. data/examples/ninesixty/extensions/ninesixty/templates/project/grid.sass +34 -0
  46. data/examples/ninesixty/extensions/ninesixty/templates/project/manifest.rb +2 -0
  47. data/examples/ninesixty/extensions/ninesixty/templates/project/text.sass +10 -0
  48. data/examples/susy/bootstrap.rb +3 -0
  49. data/examples/susy/config.rb +9 -0
  50. data/examples/susy/extensions/susy/LICENSE.txt +28 -0
  51. data/examples/susy/extensions/susy/README.mkdn +235 -0
  52. data/examples/susy/extensions/susy/compass-susy-plugin.gemspec +35 -0
  53. data/examples/susy/extensions/susy/docs/tutorial/build.sh +141 -0
  54. data/examples/susy/extensions/susy/docs/tutorial/code/01_target/src/_defaults.sass +100 -0
  55. data/examples/susy/extensions/susy/docs/tutorial/code/01_target/src/screen.sass +98 -0
  56. data/examples/susy/extensions/susy/docs/tutorial/code/02_container/src/_defaults.sass +147 -0
  57. data/examples/susy/extensions/susy/docs/tutorial/code/02_container/src/screen.sass +19 -0
  58. data/examples/susy/extensions/susy/docs/tutorial/code/03_structure/src/_defaults.sass +147 -0
  59. data/examples/susy/extensions/susy/docs/tutorial/code/03_structure/src/screen.sass +48 -0
  60. data/examples/susy/extensions/susy/docs/tutorial/code/_common/config.rb +14 -0
  61. data/examples/susy/extensions/susy/docs/tutorial/code/_common/images/grid.png +0 -0
  62. data/examples/susy/extensions/susy/docs/tutorial/code/_common/images/susy_logo.png +0 -0
  63. data/examples/susy/extensions/susy/docs/tutorial/code/_common/src/_base.sass +63 -0
  64. data/examples/susy/extensions/susy/docs/tutorial/code/_tools/Markdown.pl +1450 -0
  65. data/examples/susy/extensions/susy/docs/tutorial/code/site/src/_defaults.sass +100 -0
  66. data/examples/susy/extensions/susy/docs/tutorial/code/site/src/screen.sass +91 -0
  67. data/examples/susy/extensions/susy/docs/tutorial/figures/susy_element.png +0 -0
  68. data/examples/susy/extensions/susy/docs/tutorial/figures/susy_grid.png +0 -0
  69. data/examples/susy/extensions/susy/docs/tutorial/index.mkdn +301 -0
  70. data/examples/susy/extensions/susy/lib/susy.rb +2 -0
  71. data/examples/susy/extensions/susy/lib/susy/compass_plugin.rb +5 -0
  72. data/examples/susy/extensions/susy/lib/susy/sass_extensions.rb +79 -0
  73. data/examples/susy/extensions/susy/sass/susy/_grid.sass +128 -0
  74. data/examples/susy/extensions/susy/sass/susy/_reset.sass +7 -0
  75. data/examples/susy/extensions/susy/sass/susy/_susy.sass +23 -0
  76. data/examples/susy/extensions/susy/sass/susy/_text.sass +15 -0
  77. data/examples/susy/extensions/susy/sass/susy/_utils.sass +81 -0
  78. data/examples/susy/extensions/susy/templates/project/_base.sass +62 -0
  79. data/examples/susy/extensions/susy/templates/project/_defaults.sass +147 -0
  80. data/examples/susy/extensions/susy/templates/project/ie.sass +9 -0
  81. data/examples/susy/extensions/susy/templates/project/manifest.rb +5 -0
  82. data/examples/susy/extensions/susy/templates/project/print.sass +7 -0
  83. data/examples/susy/extensions/susy/templates/project/screen.sass +44 -0
  84. data/examples/susy/src/_base.sass +62 -0
  85. data/examples/susy/src/_defaults.sass +148 -0
  86. data/examples/susy/src/screen.sass +114 -0
  87. data/examples/yui/extensions/yui/stylesheets/_yui.sass +7 -0
  88. data/examples/yui/extensions/yui/stylesheets/yui/modules/_base.sass +70 -0
  89. data/examples/yui/extensions/yui/stylesheets/yui/modules/_fonts.sass +45 -0
  90. data/examples/yui/extensions/yui/stylesheets/yui/modules/_grids.sass +385 -0
  91. data/examples/yui/extensions/yui/stylesheets/yui/modules/_reset.sass +61 -0
  92. data/examples/yui/extensions/yui/templates/project/manifest.rb +1 -0
  93. data/examples/yui/extensions/yui/templates/project/screen.sass +4 -0
  94. data/lib/compass/app_integration/rails/configuration_defaults.rb +9 -1
  95. data/lib/compass/commands/watch_project.rb +1 -1
  96. data/lib/compass/compiler.rb +9 -1
  97. data/lib/compass/configuration.rb +23 -18
  98. data/lib/compass/configuration/adapters.rb +1 -1
  99. data/lib/compass/configuration/defaults.rb +30 -0
  100. data/lib/compass/frameworks.rb +1 -1
  101. data/lib/compass/frameworks/blueprint/stylesheets/_blueprint.sass +29 -1
  102. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_buttons.sass +84 -0
  103. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_colors.sass +33 -0
  104. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_debug.sass +9 -0
  105. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_fancy_type.sass +82 -0
  106. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_form.sass +56 -0
  107. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_grid.sass +179 -0
  108. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_ie.sass +2 -2
  109. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_interaction.sass +58 -0
  110. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_link_icons.sass +44 -0
  111. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_liquid.sass +141 -0
  112. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_print.sass +1 -4
  113. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_reset.sass +57 -2
  114. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_rtl.sass +123 -0
  115. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_scaffolding.sass +49 -0
  116. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_screen.sass +2 -29
  117. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_typography.sass +162 -0
  118. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/_utilities.sass +37 -0
  119. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_buttons.sass +2 -84
  120. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_colors.sass +2 -33
  121. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_debug.sass +2 -9
  122. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_fancy_type.sass +2 -82
  123. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_form.sass +2 -55
  124. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_grid.sass +2 -178
  125. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_interaction.sass +2 -58
  126. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_link_icons.sass +2 -44
  127. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_liquid.sass +2 -140
  128. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_reset.sass +2 -56
  129. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_rtl.sass +2 -122
  130. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_scaffolding.sass +2 -47
  131. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_typography.sass +2 -160
  132. data/lib/compass/frameworks/blueprint/stylesheets/blueprint/modules/_utilities.sass +2 -37
  133. data/lib/compass/frameworks/blueprint/templates/buttons/buttons.sass +2 -2
  134. data/lib/compass/frameworks/blueprint/templates/link_icons/link_icons.sass +1 -1
  135. data/lib/compass/frameworks/blueprint/templates/project/screen.sass +1 -7
  136. data/lib/compass/frameworks/blueprint/templates/project/welcome.html.haml +5 -2
  137. data/lib/compass/frameworks/compass/stylesheets/compass/_css3.sass +8 -0
  138. data/lib/compass/frameworks/compass/stylesheets/compass/css3/_background_clip.sass +16 -0
  139. data/lib/compass/frameworks/compass/stylesheets/compass/css3/_background_origin.sass +18 -0
  140. data/lib/compass/frameworks/compass/stylesheets/compass/css3/_background_size.sass +14 -0
  141. data/lib/compass/frameworks/compass/stylesheets/compass/css3/_box_shadow.sass +18 -10
  142. data/lib/compass/frameworks/compass/stylesheets/compass/css3/_font_face.sass +31 -0
  143. data/lib/compass/frameworks/compass/stylesheets/compass/css3/_gradient.sass +40 -0
  144. data/lib/compass/frameworks/compass/stylesheets/compass/css3/_text_shadow.sass +15 -0
  145. data/lib/compass/frameworks/compass/stylesheets/compass/css3/_transform.sass +60 -0
  146. data/lib/compass/frameworks/compass/stylesheets/compass/css3/_transition.sass +57 -0
  147. data/lib/compass/grid_builder.rb +1 -1
  148. data/lib/compass/installers/base.rb +5 -1
  149. data/lib/compass/installers/manifest.rb +1 -0
  150. data/lib/compass/logger.rb +28 -2
  151. data/lib/compass/sass_extensions/functions.rb +3 -1
  152. data/lib/compass/sass_extensions/functions/color_stop.rb +10 -0
  153. data/lib/compass/sass_extensions/functions/enumerate.rb +2 -2
  154. data/lib/compass/sass_extensions/functions/font_files.rb +11 -0
  155. data/lib/compass/sass_extensions/functions/inline_image.rb +22 -1
  156. data/lib/compass/sass_extensions/functions/urls.rb +20 -0
  157. data/lib/vendor/fssm.rb +19 -6
  158. data/lib/vendor/fssm/backends/fsevents.rb +19 -60
  159. data/lib/vendor/fssm/backends/polling.rb +20 -18
  160. data/lib/vendor/fssm/cache.rb +193 -0
  161. data/lib/vendor/fssm/ext.rb +30 -0
  162. data/lib/vendor/fssm/fsevents.rb +129 -0
  163. data/lib/vendor/fssm/monitor.rb +10 -6
  164. data/lib/vendor/fssm/path.rb +24 -21
  165. data/lib/vendor/fssm/state.rb +37 -29
  166. data/lib/vendor/fssm/support.rb +3 -7
  167. data/lib/vendor/fssm/tree.rb +176 -0
  168. data/test/command_line_helper.rb +8 -4
  169. data/test/command_line_test.rb +2 -2
  170. data/test/compass_test.rb +14 -4
  171. data/test/configuration_test.rb +5 -5
  172. data/test/fixtures/stylesheets/blueprint/css/typography.css +5 -3
  173. data/test/fixtures/stylesheets/blueprint/sass/screen.sass +1 -1
  174. data/test/fixtures/stylesheets/blueprint/sass/typography.sass +2 -2
  175. data/test/fixtures/stylesheets/compass/css/print.css +2 -8
  176. data/test/fixtures/stylesheets/image_urls/css/screen.css +2 -0
  177. data/test/fixtures/stylesheets/relative/assets/images/testing.png +0 -0
  178. data/test/fixtures/stylesheets/relative/config.rb +9 -0
  179. data/test/fixtures/stylesheets/relative/css/ie.css +1 -0
  180. data/test/fixtures/stylesheets/relative/css/print.css +1 -0
  181. data/test/fixtures/stylesheets/relative/css/screen.css +1 -0
  182. data/test/fixtures/stylesheets/relative/sass/ie.sass +6 -0
  183. data/test/fixtures/stylesheets/relative/sass/print.sass +6 -0
  184. data/test/fixtures/stylesheets/relative/sass/screen.sass +3 -0
  185. data/test/rails_integration_test.rb +1 -1
  186. data/test/sass_extensions_test.rb +2 -2
  187. metadata +120 -2
@@ -1,24 +1,26 @@
1
1
  module FSSM::Backends
2
2
  class Polling
3
- def initialize(options={})
4
- @handlers = []
5
- @latency = options[:latency] || 1
6
- end
7
-
8
- def add_path(path, preload=true)
9
- @handlers << FSSM::State.new(path, preload)
10
- end
11
-
12
- def run
13
- begin
14
- loop do
15
- start = Time.now.to_f
16
- @handlers.each {|handler| handler.refresh}
17
- nap_time = @latency - (Time.now.to_f - start)
18
- sleep nap_time if nap_time > 0
3
+ def initialize(options={})
4
+ @handlers = []
5
+ @latency = options[:latency] || 1
6
+ end
7
+
8
+ def add_path(path, preload=true)
9
+ handler = FSSM::State.new(path)
10
+ handler.refresh(path.to_pathname, true) if preload
11
+ @handlers << handler
12
+ end
13
+
14
+ def run
15
+ begin
16
+ loop do
17
+ start = Time.now.to_f
18
+ @handlers.each {|handler| handler.refresh}
19
+ nap_time = @latency - (Time.now.to_f - start)
20
+ sleep nap_time if nap_time > 0
21
+ end
22
+ rescue Interrupt
19
23
  end
20
- rescue Interrupt
21
24
  end
22
25
  end
23
26
  end
24
- end
@@ -0,0 +1,193 @@
1
+ class FSSM::Cache
2
+ module Common
3
+ include Enumerable
4
+
5
+ def initialize
6
+ @children = Hash.new
7
+ end
8
+
9
+ def each(prefix='./', &block)
10
+ @children.each do |segment, node|
11
+ cprefix = Pathname.for(prefix.dup).join(segment)
12
+ block.call(cprefix, node)
13
+ node.each(cprefix, &block)
14
+ end
15
+ end
16
+
17
+ protected
18
+
19
+ def with_lock
20
+ @mutex.lock
21
+ yield
22
+ @mutex.unlock
23
+ end
24
+
25
+ def descendant(path)
26
+ recurse_on_key(path, false)
27
+ end
28
+
29
+ def descendant!(path)
30
+ recurse_on_key(path, true)
31
+ end
32
+
33
+ def child(segment)
34
+ has_child?(segment) ? @children["#{segment}"] : nil
35
+ end
36
+
37
+ def child!(segment)
38
+ (@children["#{segment}"] ||= Node.new)
39
+ end
40
+
41
+ def has_child?(segment)
42
+ @children.include?("#{segment}")
43
+ end
44
+
45
+ def remove_child(segment)
46
+ @children.delete("#{segment}")
47
+ end
48
+
49
+ def remove_children
50
+ @children.clear
51
+ end
52
+
53
+ def recurse_on_key(key, create)
54
+ key = sanitize_key(key)
55
+ node = self
56
+
57
+ until key.empty?
58
+ segment = key.shift
59
+ node = create ? node.child!(segment) : node.child(segment)
60
+ return nil unless node
61
+ end
62
+
63
+ node
64
+ end
65
+
66
+ def key_for_path(path)
67
+ Pathname.for(path).names
68
+ end
69
+
70
+ def relative_path(path)
71
+ sanitize_path(path, false)
72
+ end
73
+
74
+ def absolute_path(path)
75
+ sanitize_path(path, true)
76
+ end
77
+
78
+ def sanitize_path(path, absolute)
79
+ if path.is_a?(Array)
80
+ first = absolute ? '/' : path.shift
81
+ path = path.inject(Pathname.new("#{first}")) do |pathname, segment|
82
+ pathname.join("#{segment}")
83
+ end
84
+ path
85
+ else
86
+ path = Pathname.for(path)
87
+ absolute ? path.expand_path : path
88
+ end
89
+ end
90
+ end
91
+
92
+ class Node
93
+ include Common
94
+
95
+ attr_accessor :mtime
96
+ attr_accessor :ftype
97
+
98
+ def <=>(other)
99
+ self.mtime <=> other.mtime
100
+ end
101
+
102
+ def from_path(path)
103
+ path = absolute_path(path)
104
+ @mtime = path.mtime
105
+ @ftype = path.ftype
106
+ end
107
+
108
+ protected
109
+
110
+ def sanitize_key(key)
111
+ key_for_path(relative_path(key))
112
+ end
113
+ end
114
+
115
+ include Common
116
+
117
+ def initialize
118
+ @mutex = Mutex.new
119
+ super
120
+ end
121
+
122
+ def clear
123
+ @mutex.lock
124
+ @children.clear
125
+ @mutex.unlock
126
+ end
127
+
128
+ def set(path)
129
+ unset(path)
130
+ node = descendant!(path)
131
+ node.from_path(path)
132
+ node.mtime
133
+ end
134
+
135
+ def unset(path='/')
136
+ key = sanitize_key(path)
137
+
138
+ if key.empty?
139
+ self.clear
140
+ return nil
141
+ end
142
+
143
+ segment = key.pop
144
+ node = descendant(key)
145
+
146
+ return unless node
147
+
148
+ @mutex.lock
149
+ node.remove_child(segment)
150
+ @mutex.unlock
151
+
152
+ nil
153
+ end
154
+
155
+ def files
156
+ ftype('file')
157
+ end
158
+
159
+ def directories
160
+ ftype('directory')
161
+ end
162
+
163
+ protected
164
+
165
+ def each(&block)
166
+ prefix='/'
167
+ super(prefix, &block)
168
+ end
169
+
170
+ def ftype(ft)
171
+ inject({}) do |hash, entry|
172
+ path, node = entry
173
+ hash["#{path}"] = node.mtime if node.ftype == ft
174
+ hash
175
+ end
176
+ end
177
+
178
+ def descendant(path)
179
+ node = recurse_on_key(path, false)
180
+ node
181
+ end
182
+
183
+ def descendant!(path)
184
+ @mutex.lock
185
+ node = recurse_on_key(path, true)
186
+ @mutex.unlock
187
+ node
188
+ end
189
+
190
+ def sanitize_key(key)
191
+ key_for_path(absolute_path(key))
192
+ end
193
+ end
@@ -4,4 +4,34 @@ class Pathname
4
4
  path.is_a?(Pathname) ? path : new(path)
5
5
  end
6
6
  end
7
+
8
+ # before overwriting chop_basename:
9
+ # %total - 29.50%
10
+ # %self - 20.50%
11
+ # after overwriting chop_basename:
12
+ # %total - 24.36%
13
+ # %self - 15.47%
14
+ CHOP_PAT = /\A#{SEPARATOR_PAT}?\z/
15
+ def chop_basename(path)
16
+ base = File.basename(path)
17
+ # the original version of this method recalculates this regexp
18
+ # each run, despite the pattern never changing.
19
+ if CHOP_PAT =~ base
20
+ return nil
21
+ else
22
+ return path[0, path.rindex(base)], base
23
+ end
24
+ end
25
+
26
+ def segments
27
+ prefix, names = split_names(@path)
28
+ names.unshift(prefix) unless prefix.empty?
29
+ names.shift if names[0] == '.'
30
+ names
31
+ end
32
+
33
+ def names
34
+ prefix, names = split_names(@path)
35
+ names
36
+ end
7
37
  end
@@ -0,0 +1,129 @@
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
+ def initialize(fsevents_object, id, path)
10
+ @fsevents_object, @id, @path = fsevents_object, id, path
11
+ end
12
+
13
+ # Returns an array of the files/dirs in the path that the event occurred in.
14
+ # The files are sorted by the modification time, the first entry is the last modified file.
15
+ def files
16
+ Dir.glob("#{File.expand_path(path)}/*").sort_by {|f| File.mtime(f) }.reverse
17
+ end
18
+
19
+ # Returns the last modified file in the path that the event occurred in.
20
+ def last_modified_file
21
+ files.first
22
+ end
23
+ end
24
+
25
+ class StreamError < StandardError; end
26
+
27
+ attr_reader :paths
28
+ attr_reader :stream
29
+
30
+ attr_accessor :allocator
31
+ attr_accessor :context
32
+ attr_accessor :since
33
+ attr_accessor :latency
34
+ attr_accessor :flags
35
+
36
+ # Initializes a new FSEvents `watchdog` object and starts watching the directories you specify for events. The
37
+ # block is used as a handler for events, which are passed as the block's argument. This method is the easiest
38
+ # way to start watching some directories if you don't care about the details of setting up the event stream.
39
+ #
40
+ # Rucola::FSEvents.start_watching('/tmp') do |events|
41
+ # events.each { |event| log.debug("#{event.files.inspect} were changed.") }
42
+ # end
43
+ #
44
+ # Rucola::FSEvents.start_watching('/var/log/system.log', '/var/log/secure.log', :since => last_id, :latency => 5) do
45
+ # Growl.notify("Something was added to your log files!")
46
+ # end
47
+ #
48
+ # Note that the method also returns the FSEvents object. This enables you to control the event stream if you want to.
49
+ #
50
+ # fsevents = Rucola::FSEvents.start_watching('/Volumes') do |events|
51
+ # events.each { |event| Growl.notify("Volume changes: #{event.files.to_sentence}") }
52
+ # end
53
+ # fsevents.stop
54
+ def self.start_watching(*params, &block)
55
+ fsevents = new(*params, &block)
56
+ fsevents.create_stream
57
+ fsevents.start
58
+ fsevents
59
+ end
60
+
61
+ # Creates a new FSEvents `watchdog` object. You can specify a list of paths to watch and options to control the
62
+ # behaviour of the watchdog. The block you pass serves as a callback when an event is generated on one of the
63
+ # specified paths.
64
+ #
65
+ # fsevents = FSEvents.new('/etc/passwd') { Mailer.send_mail("Someone touched the password file!") }
66
+ # fsevents.create_stream
67
+ # fsevents.start
68
+ #
69
+ # fsevents = FSEvents.new('/home/upload', :since => UploadWatcher.last_event_id) do |events|
70
+ # events.each do |event|
71
+ # UploadWatcher.last_event_id = event.id
72
+ # event.files.each do |file|
73
+ # UploadWatcher.logfile.append("#{file} was changed")
74
+ # end
75
+ # end
76
+ # end
77
+ #
78
+ # *:since: The service will report events that have happened after the supplied event ID. Never use 0 because that
79
+ # will cause every fsevent since the "beginning of time" to be reported. Use OSX::KFSEventStreamEventIdSinceNow
80
+ # if you want to receive events that have happened after this call. (Default: OSX::KFSEventStreamEventIdSinceNow).
81
+ # You can find the ID's passed with :since in the events passed to your block.
82
+ # *:latency: Number of seconds to wait until an FSEvent is reported, this allows the service to bundle events. (Default: 0.0)
83
+ #
84
+ # Please refer to the Cocoa documentation for the rest of the options.
85
+ def initialize(*params, &block)
86
+ raise ArgumentError, 'No callback block was specified.' unless block_given?
87
+
88
+ options = params.last.kind_of?(Hash) ? params.pop : {}
89
+ @paths = params.flatten
90
+
91
+ paths.each { |path| raise ArgumentError, "The specified path (#{path}) does not exist." unless File.exist?(path) }
92
+
93
+ @allocator = options[:allocator] || OSX::KCFAllocatorDefault
94
+ @context = options[:context] || nil
95
+ @since = options[:since] || OSX::KFSEventStreamEventIdSinceNow
96
+ @latency = options[:latency] || 0.0
97
+ @flags = options[:flags] || 0
98
+ @stream = options[:stream] || nil
99
+
100
+ @user_callback = block
101
+ @callback = Proc.new do |stream, client_callback_info, number_of_events, paths_pointer, event_flags, event_ids|
102
+ paths_pointer.regard_as('*')
103
+ events = []
104
+ number_of_events.times {|i| events << Rucola::FSEvents::FSEvent.new(self, event_ids[i], paths_pointer[i]) }
105
+ @user_callback.call(events)
106
+ end
107
+ end
108
+
109
+ # Create the stream.
110
+ # Raises a Rucola::FSEvents::StreamError if the stream could not be created.
111
+ def create_stream
112
+ @stream = OSX.FSEventStreamCreate(@allocator, @callback, @context, @paths, @since, @latency, @flags)
113
+ raise(StreamError, 'Unable to create FSEvents stream.') unless @stream
114
+ OSX.FSEventStreamScheduleWithRunLoop(@stream, OSX.CFRunLoopGetCurrent, OSX::KCFRunLoopDefaultMode)
115
+ end
116
+
117
+ # Start the stream.
118
+ # Raises a Rucola::FSEvents::StreamError if the stream could not be started.
119
+ def start
120
+ raise(StreamError, 'Unable to start FSEvents stream.') unless OSX.FSEventStreamStart(@stream)
121
+ end
122
+
123
+ # Stop the stream.
124
+ # You can resume it by calling `start` again.
125
+ def stop
126
+ OSX.FSEventStreamStop(@stream)
127
+ end
128
+ end
129
+ end
@@ -3,18 +3,22 @@ class FSSM::Monitor
3
3
  @options = options
4
4
  @backend = FSSM::Backends::Default.new
5
5
  end
6
-
6
+
7
7
  def path(*args, &block)
8
8
  path = FSSM::Path.new(*args)
9
- if block && block.arity == 0
10
- path.instance_eval(&block)
11
- elsif block && block.arity == 1
12
- block.call(path)
9
+
10
+ if block_given?
11
+ if block.arity == 1
12
+ block.call(path)
13
+ else
14
+ path.instance_eval(&block)
15
+ end
13
16
  end
17
+
14
18
  @backend.add_path(path)
15
19
  path
16
20
  end
17
-
21
+
18
22
  def run
19
23
  @backend.run
20
24
  end
@@ -3,45 +3,48 @@ class FSSM::Path
3
3
  set_path(path || '.')
4
4
  set_glob(glob || '**/*')
5
5
  init_callbacks
6
- if block && block.arity == 0
7
- self.instance_eval(&block)
8
- elsif block && block.arity == 1
9
- block.call(self)
6
+
7
+ if block_given?
8
+ if block.arity == 1
9
+ block.call(self)
10
+ else
11
+ self.instance_eval(&block)
12
+ end
10
13
  end
11
14
  end
12
-
15
+
13
16
  def to_s
14
17
  @path.to_s
15
18
  end
16
-
19
+
17
20
  def to_pathname
18
21
  @path
19
22
  end
20
-
23
+
21
24
  def glob(value=nil)
22
25
  return @glob if value.nil?
23
26
  set_glob(value)
24
27
  end
25
-
28
+
26
29
  def create(callback_or_path=nil, &block)
27
30
  callback_action(:create, (block_given? ? block : callback_or_path))
28
31
  end
29
-
32
+
30
33
  def update(callback_or_path=nil, &block)
31
34
  callback_action(:update, (block_given? ? block : callback_or_path))
32
35
  end
33
-
36
+
34
37
  def delete(callback_or_path=nil, &block)
35
38
  callback_action(:delete, (block_given? ? block : callback_or_path))
36
39
  end
37
-
40
+
38
41
  private
39
-
42
+
40
43
  def init_callbacks
41
44
  do_nothing = lambda {|base, relative|}
42
45
  @callbacks = Hash.new(do_nothing)
43
46
  end
44
-
47
+
45
48
  def callback_action(type, arg=nil)
46
49
  if arg.is_a?(Proc)
47
50
  set_callback(type, arg)
@@ -51,37 +54,37 @@ class FSSM::Path
51
54
  run_callback(type, arg)
52
55
  end
53
56
  end
54
-
57
+
55
58
  def set_callback(type, arg)
56
59
  raise ArgumentError, "Proc expected" unless arg.is_a?(Proc)
57
60
  @callbacks[type] = arg
58
61
  end
59
-
62
+
60
63
  def get_callback(type)
61
64
  @callbacks[type]
62
65
  end
63
-
66
+
64
67
  def run_callback(type, arg)
65
68
  base, relative = split_path(arg)
66
-
69
+
67
70
  begin
68
71
  @callbacks[type].call(base, relative)
69
72
  rescue Exception => e
70
73
  raise FSSM::CallbackError, "#{type} - #{base.join(relative)}: #{e.message}", e.backtrace
71
74
  end
72
75
  end
73
-
76
+
74
77
  def split_path(path)
75
78
  path = Pathname.for(path)
76
- [@path, (path.relative? ? path : path.relative_path_from(@path))]
79
+ [@path, (path.relative? ? path : path.relative_path_from(@path))]
77
80
  end
78
-
81
+
79
82
  def set_path(path)
80
83
  path = Pathname.for(path)
81
84
  raise FSSM::FileNotFoundError, "#{path}" unless path.exist?
82
85
  @path = path.realpath
83
86
  end
84
-
87
+
85
88
  def set_glob(glob)
86
89
  @glob = glob.is_a?(Array) ? glob : [glob]
87
90
  end