haml-edge 2.3.170 → 2.3.171

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/Rakefile +43 -27
  3. data/VERSION +1 -1
  4. data/test/haml/spec/README.md +97 -0
  5. data/test/haml/spec/lua_haml_spec.lua +30 -0
  6. data/test/haml/spec/ruby_haml_test.rb +19 -0
  7. data/test/haml/spec/tests.json +534 -0
  8. data/vendor/fssm/LICENSE +20 -0
  9. data/vendor/fssm/README.markdown +55 -0
  10. data/vendor/fssm/Rakefile +59 -0
  11. data/vendor/fssm/VERSION.yml +5 -0
  12. data/vendor/fssm/example.rb +9 -0
  13. data/vendor/fssm/fssm.gemspec +77 -0
  14. data/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  15. data/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  16. data/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  17. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  18. data/vendor/fssm/lib/fssm/monitor.rb +26 -0
  19. data/vendor/fssm/lib/fssm/path.rb +91 -0
  20. data/vendor/fssm/lib/fssm/pathname.rb +502 -0
  21. data/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  22. data/vendor/fssm/lib/fssm/state/file.rb +24 -0
  23. data/vendor/fssm/lib/fssm/support.rb +63 -0
  24. data/vendor/fssm/lib/fssm/tree.rb +176 -0
  25. data/vendor/fssm/lib/fssm.rb +33 -0
  26. data/vendor/fssm/profile/prof-cache.rb +40 -0
  27. data/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  28. data/vendor/fssm/profile/prof-pathname.rb +68 -0
  29. data/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  30. data/vendor/fssm/profile/prof.html +2379 -0
  31. data/vendor/fssm/spec/path_spec.rb +75 -0
  32. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  33. data/vendor/fssm/spec/root/file.css +0 -0
  34. data/vendor/fssm/spec/root/file.rb +0 -0
  35. data/vendor/fssm/spec/root/file.yml +0 -0
  36. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  37. data/vendor/fssm/spec/spec_helper.rb +14 -0
  38. metadata +36 -1
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Travis Tilley
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,55 @@
1
+ Monitor API
2
+ ===========
3
+
4
+ There are three ways you can run the monitor.
5
+
6
+ 1. call monitor with a path parameter, and define callbacks in a block
7
+ 2. call monitor with a block to configure multiple paths and callbacks
8
+ 3. create a monitor object and run each step manually
9
+
10
+ Monitor with path
11
+ -----------------
12
+
13
+ This form watches one path, and enters the run loop automatically. The first parameter is the path to watch, and the second parameter is an optional glob pattern or array of glob patterns that a file must match in order to trigger a callback. The default glob, if ommitted, is `'**/*'`.
14
+
15
+ FSSM.monitor('/some/directory/', '**/*') do
16
+ update {|base, relative|}
17
+ delete {|base, relative|}
18
+ create {|base, relative|}
19
+ end
20
+
21
+ Monitor with block
22
+ ------------------
23
+
24
+ This form watches one or more paths, and enters the run loop automatically. The glob configuration call can be ommitted, and defaults to `'**/*'`.
25
+
26
+ FSSM.monitor do
27
+ path '/some/directory/' do
28
+ glob '**/*.yml'
29
+
30
+ update {|base, relative|}
31
+ delete {|base, relative|}
32
+ create {|base, relative|}
33
+ end
34
+
35
+ path '/some/other/directory/' do
36
+ update {|base, relative|}
37
+ delete {|base, relative|}
38
+ create {|base, relative|}
39
+ end
40
+ end
41
+
42
+ Monitor object
43
+ --------------
44
+
45
+ This form doesn't enter the run loop automatically.
46
+
47
+ monitor = FSSM::Monitor.new
48
+
49
+ monitor.path '/some/directory/' do
50
+ update {|base, relative|}
51
+ delete {|base, relative|}
52
+ create {|base, relative|}
53
+ end
54
+
55
+ monitor.run
@@ -0,0 +1,59 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "fssm"
8
+ gem.summary = %Q{file system state monitor}
9
+ gem.description = %Q{file system state monitor}
10
+ gem.email = "ttilley@gmail.com"
11
+ gem.homepage = "http://github.com/ttilley/fssm"
12
+ gem.authors = ["Travis Tilley"]
13
+ gem.add_development_dependency "rspec"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
18
+ end
19
+
20
+ require 'spec/rake/spectask'
21
+ Spec::Rake::SpecTask.new(:spec) do |spec|
22
+ spec.libs << 'lib' << 'spec'
23
+ spec.spec_files = FileList['spec/**/*_spec.rb']
24
+ end
25
+
26
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.pattern = 'spec/**/*_spec.rb'
29
+ spec.rcov = true
30
+ end
31
+
32
+ task :spec => :check_dependencies
33
+
34
+ begin
35
+ require 'reek/rake_task'
36
+ Reek::RakeTask.new do |t|
37
+ t.fail_on_error = true
38
+ t.verbose = false
39
+ t.source_files = 'lib/**/*.rb'
40
+ end
41
+ rescue LoadError
42
+ task :reek do
43
+ abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
44
+ end
45
+ end
46
+
47
+ begin
48
+ require 'roodi'
49
+ require 'roodi_task'
50
+ RoodiTask.new do |t|
51
+ t.verbose = false
52
+ end
53
+ rescue LoadError
54
+ task :roodi do
55
+ abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
56
+ end
57
+ end
58
+
59
+ task :default => :spec
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 3
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.3"
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-01-30}
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.5}
57
+ s.summary = %q{file system state monitor}
58
+ s.test_files = [
59
+ "spec/path_spec.rb",
60
+ "spec/root/file.rb",
61
+ "spec/spec_helper.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,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