guard 0.1.1 → 0.2.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -4,17 +4,17 @@ Guard is a command line tool to easly handle events on files modifications.
4
4
 
5
5
  == Features
6
6
 
7
- - FSEvent support on Mac OS X (without RubyCocoa!)
8
- - Inotify support on Linux (beta)
9
- - Super fast change detection
7
+ - FSEvent support on Mac OS X 10.5+ (without RubyCocoa!, please install {rb-fsevent, >= 0.3.2}[https://rubygems.org/gems/rb-fsevent])
8
+ - Inotify support on Linux (beta, please install {rb-inotify, >= 0.5.1}[https://rubygems.org/gems/rb-inotify])
9
+ - Polling for others (help us to support more systems)
10
+ - Super fast change detection (when polling not used)
10
11
  - Automatic files modifications detection (even new files are detected)
11
12
  - Growl notification (please install {growlnotify}[http://growl.info/documentation/growlnotify.php])
12
13
  - Libnotify notification
14
+ - Tested on Ruby 1.8.7 & 1.9.2.
13
15
 
14
16
  == Install
15
17
 
16
- Only Mac OS X (10.5+) & Linux are supported. Tested on Ruby 1.8.7 & 1.9.2.
17
-
18
18
  Install the gem:
19
19
 
20
20
  gem install guard
@@ -35,9 +35,13 @@ Just launch Guard inside your ruby/rails project with:
35
35
 
36
36
  guard
37
37
 
38
+ Shell can be cleared after each change with:
39
+
40
+ guard -c
41
+
38
42
  Options list is available with:
39
43
 
40
- guard help
44
+ guard help [TASK]
41
45
 
42
46
  Signal handlers are used to interact with Guard:
43
47
 
@@ -48,11 +52,11 @@ Signal handlers are used to interact with Guard:
48
52
  == Available Guards
49
53
 
50
54
  - {guard-rspec}[http://github.com/guard/guard-rspec]
55
+ - {guard-livereload}[http://github.com/guard/guard-livereload]
51
56
 
52
57
  guard ideas:
53
58
 
54
59
  - guard-spork
55
- - guard-livereload
56
60
  - guard-cucumber
57
61
  - guard-test
58
62
  - guard-sass
@@ -65,7 +69,7 @@ Add it to your Gemfile (inside test group):
65
69
 
66
70
  gem '<guard-name>'
67
71
 
68
- Add guard definition to your Guardfile with:
72
+ Add guard definition to your Guardfile by running this command:
69
73
 
70
74
  guard init <guard-name>
71
75
 
data/lib/guard.rb CHANGED
@@ -14,7 +14,7 @@ module Guard
14
14
 
15
15
  def start(options = {})
16
16
  @options = options
17
- @listener = Listener.new
17
+ @listener = Listener.init
18
18
  @guards = []
19
19
 
20
20
  Dsl.evaluate_guardfile
@@ -59,7 +59,7 @@ module Guard
59
59
 
60
60
  def run
61
61
  listener.stop
62
- UI.clear if options[:clear]
62
+ UI. clear if options[:clear]
63
63
  yield
64
64
  listener.start
65
65
  end
@@ -1,51 +1,39 @@
1
- require 'sys/uname'
1
+ require 'rbconfig'
2
2
 
3
3
  module Guard
4
+
5
+ autoload :Darwin, 'guard/listeners/darwin'
6
+ autoload :Linux, 'guard/listeners/linux'
7
+ autoload :Polling, 'guard/listeners/polling'
8
+
4
9
  class Listener
5
- attr_reader :last_event, :callback, :pipe
6
-
7
- def initialize
8
- update_last_event
9
- end
10
-
11
- def on_change(&block)
12
- @callback = block
13
- end
14
-
15
- def start
16
- @pipe = case Sys::Uname.sysname
17
- when 'Darwin'
18
- IO.popen("#{bin_path}/fsevent_watch .")
19
- when 'Linux'
20
- IO.popen("#{bin_path}/inotify_watch .")
10
+ attr_reader :last_event
11
+
12
+ def self.init
13
+ if mac? && Darwin.usable?
14
+ Darwin.new
15
+ elsif linux? && Linux.usable?
16
+ Linux.new
17
+ else
18
+ UI.info "Using polling (Please help us to support your system better than that.)"
19
+ Polling.new
21
20
  end
22
- watch_change
23
21
  end
24
22
 
25
- def stop
26
- Process.kill("HUP", pipe.pid) if pipe
23
+ def initialize
24
+ update_last_event
27
25
  end
28
26
 
29
27
  private
30
28
 
31
- def watch_change
32
- while !pipe.eof?
33
- if line = pipe.readline
34
- modified_dirs = line.split(" ")
35
- files = modified_files(modified_dirs)
36
- update_last_event
37
- callback.call(files)
38
- end
39
- end
40
- end
41
-
42
- def modified_files(dirs)
43
- files = potentially_modified_files(dirs).select { |file| recent_file?(file) }
29
+ def modified_files(dirs, options = {})
30
+ files = potentially_modified_files(dirs, options).select { |path| File.file?(path) && recent_file?(path) }
44
31
  files.map! { |file| file.gsub("#{Dir.pwd}/", '') }
45
32
  end
46
33
 
47
- def potentially_modified_files(dirs)
48
- Dir.glob(dirs.map { |dir| "#{dir}*" })
34
+ def potentially_modified_files(dirs, options = {})
35
+ match = options[:all] ? "**/*" : "*"
36
+ Dir.glob(dirs.map { |dir| "#{dir}#{match}" })
49
37
  end
50
38
 
51
39
  def recent_file?(file)
@@ -58,8 +46,12 @@ module Guard
58
46
  @last_event = Time.now
59
47
  end
60
48
 
61
- def bin_path
62
- File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin'))
49
+ def self.mac?
50
+ Config::CONFIG['target_os'] =~ /darwin/i
51
+ end
52
+
53
+ def self.linux?
54
+ Config::CONFIG['target_os'] =~ /linux/i
63
55
  end
64
56
 
65
57
  end
@@ -0,0 +1,40 @@
1
+ module Guard
2
+ class Darwin < Listener
3
+ attr_reader :fsevent
4
+
5
+ def initialize
6
+ super
7
+ @fsevent = FSEvent.new
8
+ end
9
+
10
+ def on_change(&callback)
11
+ @fsevent.watch Dir.pwd do |modified_dirs|
12
+ files = modified_files(modified_dirs)
13
+ update_last_event
14
+ callback.call(files)
15
+ end
16
+ end
17
+
18
+ def start
19
+ @fsevent.run
20
+ end
21
+
22
+ def stop
23
+ @fsevent.stop
24
+ end
25
+
26
+ def self.usable?
27
+ require 'rb-fsevent'
28
+ if !defined?(FSEvent::VERSION) || Gem::Version.new(FSEvent::VERSION) < Gem::Version.new('0.3.2')
29
+ UI.info "Please update rb-fsevent (>= 0.3.2)"
30
+ false
31
+ else
32
+ true
33
+ end
34
+ rescue LoadError
35
+ UI.info "Please install rb-fsevent gem for Mac OSX FSEvents support"
36
+ false
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,58 @@
1
+ module Guard
2
+ class Linux < Listener
3
+ attr_reader :inotify, :files, :latency, :callback
4
+
5
+ def initialize
6
+ @inotify = INotify::Notifier.new
7
+ @files = []
8
+ @latency = 0.5
9
+ end
10
+
11
+ def on_change(&callback)
12
+ @callback = callback
13
+ inotify.watch(Dir.pwd, :recursive, :attrib, :modify, :create) do |event|
14
+ unless event.name == "" # Event on root directory
15
+ @files << event.absolute_name
16
+ end
17
+ end
18
+ end
19
+
20
+ def start
21
+ @stop = false
22
+ watch_change
23
+ end
24
+
25
+ def stop
26
+ @stop = true
27
+ inotify.stop
28
+ end
29
+
30
+ def self.usable?
31
+ require 'rb-inotify'
32
+ if !defined?(INotify::VERSION) || Gem::Version.new(INotify::VERSION) < Gem::Version.new('0.5.1')
33
+ UI.info "Please update rb-inotify (>= 0.5.1)"
34
+ false
35
+ else
36
+ true
37
+ end
38
+ rescue LoadError
39
+ UI.info "Please install rb-inotify gem for Linux inotify support"
40
+ false
41
+ end
42
+
43
+ private
44
+
45
+ def watch_change
46
+ while !@stop
47
+ inotify.process
48
+ unless files.empty?
49
+ files.map! { |file| file.gsub("#{Dir.pwd}/", '') }
50
+ callback.call(files)
51
+ files.clear
52
+ end
53
+ sleep latency
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,37 @@
1
+ module Guard
2
+ class Polling < Listener
3
+ attr_reader :callback, :latency
4
+
5
+ def initialize
6
+ super
7
+ @latency = 1.5
8
+ end
9
+
10
+ def on_change(&callback)
11
+ @callback = callback
12
+ end
13
+
14
+ def start
15
+ @stop = false
16
+ watch_change
17
+ end
18
+
19
+ def stop
20
+ @stop = true
21
+ end
22
+
23
+ private
24
+
25
+ def watch_change
26
+ while !@stop
27
+ start = Time.now.to_f
28
+ files = modified_files([Dir.pwd + '/'], :all => true)
29
+ update_last_event
30
+ callback.call(files) unless files.empty?
31
+ nap_time = latency - (Time.now.to_f - start)
32
+ sleep(nap_time) if nap_time > 0
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -1,10 +1,10 @@
1
- require 'sys/uname'
1
+ require 'rbconfig'
2
2
  require 'pathname'
3
3
 
4
- case Sys::Uname.sysname
5
- when 'Darwin'
4
+ case Config::CONFIG['target_os']
5
+ when /darwin/i
6
6
  require 'growl'
7
- when 'Linux'
7
+ when /linux/i
8
8
  require 'libnotify'
9
9
  end
10
10
 
@@ -15,10 +15,10 @@ module Guard
15
15
  unless ENV["GUARD_ENV"] == "test"
16
16
  image = options[:image] || :success
17
17
  title = options[:title] || "Guard"
18
- case Sys::Uname.sysname
19
- when 'Darwin'
18
+ case Config::CONFIG['target_os']
19
+ when /darwin/i
20
20
  Growl.notify message, :title => title, :icon => image_path(image), :name => "Guard"
21
- when 'Linux'
21
+ when /linux/i
22
22
  Libnotify.show :body => message, :summary => title, :icon_path => image_path(image)
23
23
  end
24
24
  end
data/lib/guard/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Guard
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0.beta.1"
3
3
  end
metadata CHANGED
@@ -1,13 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guard
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
5
- prerelease: false
4
+ hash: 62196353
5
+ prerelease: true
6
6
  segments:
7
7
  - 0
8
+ - 2
9
+ - 0
10
+ - beta
8
11
  - 1
9
- - 1
10
- version: 0.1.1
12
+ version: 0.2.0.beta.1
11
13
  platform: ruby
12
14
  authors:
13
15
  - Thibaud Guillaume-Gentil
@@ -15,7 +17,7 @@ autorequire:
15
17
  bindir: bin
16
18
  cert_chain: []
17
19
 
18
- date: 2010-10-10 00:00:00 +02:00
20
+ date: 2010-10-17 00:00:00 +02:00
19
21
  default_executable:
20
22
  dependencies:
21
23
  - !ruby/object:Gem::Dependency
@@ -26,13 +28,12 @@ dependencies:
26
28
  requirements:
27
29
  - - ~>
28
30
  - !ruby/object:Gem::Version
29
- hash: 7712058
31
+ hash: 15
30
32
  segments:
31
33
  - 2
32
34
  - 0
33
35
  - 0
34
- - rc
35
- version: 2.0.0.rc
36
+ version: 2.0.0
36
37
  type: :development
37
38
  version_requirements: *id001
38
39
  - !ruby/object:Gem::Dependency
@@ -43,12 +44,12 @@ dependencies:
43
44
  requirements:
44
45
  - - ~>
45
46
  - !ruby/object:Gem::Version
46
- hash: 27
47
+ hash: 29
47
48
  segments:
48
49
  - 0
49
50
  - 1
50
- - 0
51
- version: 0.1.0
51
+ - 3
52
+ version: 0.1.3
52
53
  type: :development
53
54
  version_requirements: *id002
54
55
  - !ruby/object:Gem::Dependency
@@ -83,26 +84,10 @@ dependencies:
83
84
  version: 0.14.3
84
85
  type: :runtime
85
86
  version_requirements: *id004
86
- - !ruby/object:Gem::Dependency
87
- name: sys-uname
88
- prerelease: false
89
- requirement: &id005 !ruby/object:Gem::Requirement
90
- none: false
91
- requirements:
92
- - - ~>
93
- - !ruby/object:Gem::Version
94
- hash: 55
95
- segments:
96
- - 0
97
- - 8
98
- - 4
99
- version: 0.8.4
100
- type: :runtime
101
- version_requirements: *id005
102
87
  - !ruby/object:Gem::Dependency
103
88
  name: growl
104
89
  prerelease: false
105
- requirement: &id006 !ruby/object:Gem::Requirement
90
+ requirement: &id005 !ruby/object:Gem::Requirement
106
91
  none: false
107
92
  requirements:
108
93
  - - ~>
@@ -114,27 +99,11 @@ dependencies:
114
99
  - 3
115
100
  version: 1.0.3
116
101
  type: :runtime
117
- version_requirements: *id006
118
- - !ruby/object:Gem::Dependency
119
- name: rb-inotify
120
- prerelease: false
121
- requirement: &id007 !ruby/object:Gem::Requirement
122
- none: false
123
- requirements:
124
- - - ~>
125
- - !ruby/object:Gem::Version
126
- hash: 61
127
- segments:
128
- - 0
129
- - 8
130
- - 1
131
- version: 0.8.1
132
- type: :runtime
133
- version_requirements: *id007
102
+ version_requirements: *id005
134
103
  - !ruby/object:Gem::Dependency
135
104
  name: libnotify
136
105
  prerelease: false
137
- requirement: &id008 !ruby/object:Gem::Requirement
106
+ requirement: &id006 !ruby/object:Gem::Requirement
138
107
  none: false
139
108
  requirements:
140
109
  - - ~>
@@ -146,19 +115,18 @@ dependencies:
146
115
  - 3
147
116
  version: 0.1.3
148
117
  type: :runtime
149
- version_requirements: *id008
118
+ version_requirements: *id006
150
119
  description: Guard is a command line tool to easily handle events on files modifications.
151
120
  email:
152
121
  - thibaud@thibaud.me
153
122
  executables:
154
123
  - guard
155
- extensions:
156
- - ext/extconf.rb
124
+ extensions: []
125
+
157
126
  extra_rdoc_files: []
158
127
 
159
128
  files:
160
129
  - bin/guard
161
- - bin/inotify_watch
162
130
  - images/failed.png
163
131
  - images/pending.png
164
132
  - images/success.png
@@ -167,14 +135,15 @@ files:
167
135
  - lib/guard/guard.rb
168
136
  - lib/guard/interactor.rb
169
137
  - lib/guard/listener.rb
138
+ - lib/guard/listeners/darwin.rb
139
+ - lib/guard/listeners/linux.rb
140
+ - lib/guard/listeners/polling.rb
170
141
  - lib/guard/notifier.rb
171
142
  - lib/guard/templates/Guardfile
172
143
  - lib/guard/ui.rb
173
144
  - lib/guard/version.rb
174
145
  - lib/guard/watcher.rb
175
146
  - lib/guard.rb
176
- - ext/extconf.rb
177
- - ext/fsevent/fsevent_watch.c
178
147
  - LICENSE
179
148
  - README.rdoc
180
149
  has_rdoc: true
data/bin/inotify_watch DELETED
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'rubygems'
3
- require 'rb-inotify'
4
-
5
- folders = Array.new
6
- notifier = INotify::Notifier.new
7
-
8
- notifier.watch(ARGV.first || '.', :modify, :recursive) do |event|
9
- dir = File.expand_path(File.dirname(event.absolute_name)) + '/'
10
- if !folders.include?(dir)
11
- folders << dir
12
- end
13
- end
14
-
15
- while true do
16
- notifier.process
17
-
18
- if !folders.empty?
19
- $stdout.puts folders.join(' ')
20
- $stdout.flush
21
- folders.clear
22
- end
23
-
24
- sleep(0.1)
25
- end
data/ext/extconf.rb DELETED
@@ -1,18 +0,0 @@
1
- # Workaround to make Rubygems believe it builds a native gem
2
- require 'mkmf'
3
- create_makefile('none')
4
-
5
- if `uname -s`.chomp == 'Darwin'
6
- gem_root = File.expand_path(File.join('..'))
7
- darwin_verion = `uname -r`.to_i
8
- sdk_verion = { 9 => '10.5', 10 => '10.6', 11 => '10.7' }[darwin_verion]
9
-
10
- raise "Darwin #{darwin_verion} is not supported" unless sdk_verion
11
-
12
- # Compile the actual fsevent_watch binary
13
- system("CFLAGS='-isysroot /Developer/SDKs/MacOSX#{sdk_verion}.sdk -mmacosx-version-min=#{sdk_verion}' /usr/bin/gcc -framework CoreServices -o '#{gem_root}/bin/fsevent_watch' fsevent/fsevent_watch.c")
14
-
15
- unless File.executable?("#{gem_root}/bin/fsevent_watch")
16
- raise "Compilation of fsevent_watch failed (see README)"
17
- end
18
- end
@@ -1,44 +0,0 @@
1
- #include <CoreServices/CoreServices.h>
2
-
3
- void callback(ConstFSEventStreamRef streamRef,
4
- void *clientCallBackInfo,
5
- size_t numEvents,
6
- void *eventPaths,
7
- const FSEventStreamEventFlags eventFlags[],
8
- const FSEventStreamEventId eventIds[]
9
- ) {
10
- // Print modified dirs
11
- int i;
12
- char **paths = eventPaths;
13
- for (i = 0; i < numEvents; i++) {
14
- printf("%s", paths[i]);
15
- printf(" ");
16
- }
17
- printf("\n");
18
- fflush(stdout);
19
- }
20
-
21
- int main (int argc, const char * argv[]) {
22
- // Create event stream
23
- CFStringRef pathToWatch = CFStringCreateWithCString(kCFAllocatorDefault, argv[1], kCFStringEncodingUTF8);
24
- CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&pathToWatch, 1, NULL);
25
- void *callbackInfo = NULL;
26
- FSEventStreamRef stream;
27
- CFAbsoluteTime latency = 0.1;
28
- stream = FSEventStreamCreate(
29
- kCFAllocatorDefault,
30
- callback,
31
- callbackInfo,
32
- pathsToWatch,
33
- kFSEventStreamEventIdSinceNow,
34
- latency,
35
- kFSEventStreamCreateFlagNone
36
- );
37
-
38
- // Add stream to run loop
39
- FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
40
- FSEventStreamStart(stream);
41
- CFRunLoopRun();
42
-
43
- return 2;
44
- }