listen 0.7.3 → 1.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +70 -35
- data/README.md +93 -76
- data/lib/listen.rb +34 -19
- data/lib/listen/adapter.rb +179 -81
- data/lib/listen/adapters/bsd.rb +27 -64
- data/lib/listen/adapters/darwin.rb +21 -58
- data/lib/listen/adapters/linux.rb +23 -55
- data/lib/listen/adapters/polling.rb +25 -34
- data/lib/listen/adapters/windows.rb +50 -46
- data/lib/listen/directory_record.rb +88 -58
- data/lib/listen/listener.rb +111 -37
- data/lib/listen/multi_listener.rb +5 -133
- data/lib/listen/turnstile.rb +9 -5
- data/lib/listen/version.rb +1 -1
- metadata +69 -22
- data/lib/listen/dependency_manager.rb +0 -126
@@ -1,143 +1,15 @@
|
|
1
1
|
module Listen
|
2
2
|
class MultiListener < Listener
|
3
|
-
attr_reader :directories, :directories_records, :adapter
|
4
3
|
|
5
|
-
#
|
4
|
+
# This class is deprecated, please use Listen::Listener instead.
|
6
5
|
#
|
7
|
-
# @
|
8
|
-
# @
|
9
|
-
# @option options [Regexp] ignore a pattern for ignoring paths
|
10
|
-
# @option options [Regexp] filter a pattern for filtering paths
|
11
|
-
# @option options [Float] latency the delay between checking for changes in seconds
|
12
|
-
# @option options [Boolean] force_polling whether to force the polling adapter or not
|
13
|
-
# @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
|
14
|
-
#
|
15
|
-
# @yield [modified, added, removed] the changed files
|
16
|
-
# @yieldparam [Array<String>] modified the list of modified files
|
17
|
-
# @yieldparam [Array<String>] added the list of added files
|
18
|
-
# @yieldparam [Array<String>] removed the list of removed files
|
6
|
+
# @see Listen::Listener
|
7
|
+
# @deprecated
|
19
8
|
#
|
20
9
|
def initialize(*args, &block)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@block = block
|
25
|
-
@directories = directories.map { |d| Pathname.new(d).realpath.to_s }
|
26
|
-
@directories_records = @directories.map { |d| DirectoryRecord.new(d) }
|
27
|
-
|
28
|
-
ignore(*options.delete(:ignore)) if options[:ignore]
|
29
|
-
filter(*options.delete(:filter)) if options[:filter]
|
30
|
-
|
31
|
-
@adapter_options = options
|
32
|
-
end
|
33
|
-
|
34
|
-
# Starts the listener by initializing the adapter and building
|
35
|
-
# the directory record concurrently, then it starts the adapter to watch
|
36
|
-
# for changes.
|
37
|
-
#
|
38
|
-
# @param [Boolean] blocking whether or not to block the current thread after starting
|
39
|
-
#
|
40
|
-
def start(blocking = true)
|
41
|
-
t = Thread.new { @directories_records.each { |r| r.build } }
|
42
|
-
@adapter = initialize_adapter
|
43
|
-
t.join
|
44
|
-
@adapter.start(blocking)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Unpauses the listener.
|
48
|
-
#
|
49
|
-
# @return [Listen::Listener] the listener
|
50
|
-
#
|
51
|
-
def unpause
|
52
|
-
@directories_records.each { |r| r.build }
|
53
|
-
@adapter.paused = false
|
54
|
-
self
|
55
|
-
end
|
56
|
-
|
57
|
-
# Adds ignored paths to the listener.
|
58
|
-
#
|
59
|
-
# @param (see Listen::DirectoryRecord#ignore)
|
60
|
-
#
|
61
|
-
# @return [Listen::Listener] the listener
|
62
|
-
#
|
63
|
-
def ignore(*paths)
|
64
|
-
@directories_records.each { |r| r.ignore(*paths) }
|
65
|
-
self
|
66
|
-
end
|
67
|
-
|
68
|
-
# Replaces ignored paths in the listener.
|
69
|
-
#
|
70
|
-
# @param (see Listen::DirectoryRecord#ignore!)
|
71
|
-
#
|
72
|
-
# @return [Listen::Listener] the listener
|
73
|
-
#
|
74
|
-
def ignore!(*paths)
|
75
|
-
@directories_records.each { |r| r.ignore!(*paths) }
|
76
|
-
self
|
77
|
-
end
|
78
|
-
|
79
|
-
# Adds file filters to the listener.
|
80
|
-
#
|
81
|
-
# @param (see Listen::DirectoryRecord#filter)
|
82
|
-
#
|
83
|
-
# @return [Listen::Listener] the listener
|
84
|
-
#
|
85
|
-
def filter(*regexps)
|
86
|
-
@directories_records.each { |r| r.filter(*regexps) }
|
87
|
-
self
|
88
|
-
end
|
89
|
-
|
90
|
-
# Replaces file filters in the listener.
|
91
|
-
#
|
92
|
-
# @param (see Listen::DirectoryRecord#filter!)
|
93
|
-
#
|
94
|
-
# @return [Listen::Listener] the listener
|
95
|
-
#
|
96
|
-
def filter!(*regexps)
|
97
|
-
@directories_records.each { |r| r.filter!(*regexps) }
|
98
|
-
self
|
10
|
+
Kernel.warn "[Listen warning]:\nListen::MultiListener is deprecated, please use Listen::Listener instead."
|
11
|
+
super
|
99
12
|
end
|
100
13
|
|
101
|
-
# Runs the callback passing it the changes if there are any.
|
102
|
-
#
|
103
|
-
# @param (see Listen::DirectoryRecord#fetch_changes)
|
104
|
-
#
|
105
|
-
def on_change(directories_to_search, options = {})
|
106
|
-
changes = fetch_records_changes(directories_to_search, options)
|
107
|
-
unless changes.values.all? { |paths| paths.empty? }
|
108
|
-
@block.call(changes[:modified],changes[:added],changes[:removed])
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
# Initializes an adapter passing it the callback and adapters' options.
|
115
|
-
#
|
116
|
-
def initialize_adapter
|
117
|
-
callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
|
118
|
-
Adapter.select_and_initialize(@directories, @adapter_options, &callback)
|
119
|
-
end
|
120
|
-
|
121
|
-
# Returns the sum of all the changes to the directories records
|
122
|
-
#
|
123
|
-
# @param (see Listen::DirectoryRecord#fetch_changes)
|
124
|
-
#
|
125
|
-
# @return [Hash] the changes
|
126
|
-
#
|
127
|
-
def fetch_records_changes(directories_to_search, options)
|
128
|
-
@directories_records.inject({}) do |h, r|
|
129
|
-
# directory records skips paths outside their range, so passing the
|
130
|
-
# whole `directories` array is not a problem.
|
131
|
-
record_changes = r.fetch_changes(directories_to_search, options.merge(:relative_paths => DEFAULT_TO_RELATIVE_PATHS))
|
132
|
-
|
133
|
-
if h.empty?
|
134
|
-
h.merge!(record_changes)
|
135
|
-
else
|
136
|
-
h.each { |k, v| h[k] += record_changes[k] }
|
137
|
-
end
|
138
|
-
|
139
|
-
h
|
140
|
-
end
|
141
|
-
end
|
142
14
|
end
|
143
15
|
end
|
data/lib/listen/turnstile.rb
CHANGED
@@ -1,28 +1,32 @@
|
|
1
1
|
module Listen
|
2
|
+
|
2
3
|
# Allows two threads to wait on eachother.
|
3
4
|
#
|
4
5
|
# @note Only two threads can be used with this Turnstile
|
5
6
|
# because of the current implementation.
|
6
7
|
class Turnstile
|
8
|
+
attr_accessor :queue
|
7
9
|
|
8
10
|
# Initialize the turnstile.
|
9
11
|
#
|
10
12
|
def initialize
|
11
|
-
# Until
|
13
|
+
# Until Ruby offers semahpores, only queues can be used
|
12
14
|
# to implement a turnstile.
|
13
|
-
@
|
15
|
+
@queue = Queue.new
|
14
16
|
end
|
15
17
|
|
16
18
|
# Blocks the current thread until a signal is received.
|
17
19
|
#
|
18
20
|
def wait
|
19
|
-
|
21
|
+
queue.pop if queue.num_waiting == 0
|
20
22
|
end
|
21
23
|
|
22
|
-
# Unblocks the waiting thread if
|
24
|
+
# Unblocks the waiting thread if any.
|
23
25
|
#
|
24
26
|
def signal
|
25
|
-
|
27
|
+
queue.push(:dummy) if queue.num_waiting == 1
|
26
28
|
end
|
29
|
+
|
27
30
|
end
|
31
|
+
|
28
32
|
end
|
data/lib/listen/version.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: listen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Thibaud Guillaume-Gentil
|
@@ -10,22 +9,76 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2013-
|
12
|
+
date: 2013-04-20 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rb-fsevent
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 0.9.3
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.9.3
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rb-inotify
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0.9'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0.9'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rb-kqueue
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0.2'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0.2'
|
15
56
|
- !ruby/object:Gem::Dependency
|
16
57
|
name: bundler
|
17
58
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
59
|
requirements:
|
20
|
-
- -
|
60
|
+
- - '>='
|
21
61
|
- !ruby/object:Gem::Version
|
22
62
|
version: '0'
|
23
63
|
type: :development
|
24
64
|
prerelease: false
|
25
65
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
66
|
requirements:
|
28
|
-
- -
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - '>='
|
29
82
|
- !ruby/object:Gem::Version
|
30
83
|
version: '0'
|
31
84
|
description: The Listen gem listens to file modifications and notifies you about the
|
@@ -37,48 +90,42 @@ executables: []
|
|
37
90
|
extensions: []
|
38
91
|
extra_rdoc_files: []
|
39
92
|
files:
|
40
|
-
- lib/listen/
|
41
|
-
- lib/listen/version.rb
|
42
|
-
- lib/listen/adapters/darwin.rb
|
93
|
+
- lib/listen/adapter.rb
|
43
94
|
- lib/listen/adapters/bsd.rb
|
95
|
+
- lib/listen/adapters/darwin.rb
|
44
96
|
- lib/listen/adapters/linux.rb
|
45
97
|
- lib/listen/adapters/polling.rb
|
46
98
|
- lib/listen/adapters/windows.rb
|
47
99
|
- lib/listen/directory_record.rb
|
100
|
+
- lib/listen/listener.rb
|
48
101
|
- lib/listen/multi_listener.rb
|
49
102
|
- lib/listen/turnstile.rb
|
50
|
-
- lib/listen/
|
51
|
-
- lib/listen/adapter.rb
|
103
|
+
- lib/listen/version.rb
|
52
104
|
- lib/listen.rb
|
53
105
|
- CHANGELOG.md
|
54
106
|
- LICENSE
|
55
107
|
- README.md
|
56
108
|
homepage: https://github.com/guard/listen
|
57
109
|
licenses: []
|
110
|
+
metadata: {}
|
58
111
|
post_install_message:
|
59
112
|
rdoc_options: []
|
60
113
|
require_paths:
|
61
114
|
- lib
|
62
115
|
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
116
|
requirements:
|
65
|
-
- -
|
117
|
+
- - '>='
|
66
118
|
- !ruby/object:Gem::Version
|
67
119
|
version: '0'
|
68
|
-
segments:
|
69
|
-
- 0
|
70
|
-
hash: -750859891
|
71
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
-
none: false
|
73
121
|
requirements:
|
74
|
-
- -
|
122
|
+
- - '>='
|
75
123
|
- !ruby/object:Gem::Version
|
76
124
|
version: 1.3.6
|
77
125
|
requirements: []
|
78
126
|
rubyforge_project: listen
|
79
|
-
rubygems_version:
|
127
|
+
rubygems_version: 2.0.3
|
80
128
|
signing_key:
|
81
|
-
specification_version:
|
129
|
+
specification_version: 4
|
82
130
|
summary: Listen to file modifications
|
83
131
|
test_files: []
|
84
|
-
has_rdoc:
|
@@ -1,126 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module Listen
|
4
|
-
|
5
|
-
# The dependency-manager offers a simple DSL which allows
|
6
|
-
# classes to declare their gem dependencies and load them when
|
7
|
-
# needed.
|
8
|
-
# It raises a user-friendly exception when the dependencies
|
9
|
-
# can't be loaded which has the install command in the message.
|
10
|
-
#
|
11
|
-
module DependencyManager
|
12
|
-
|
13
|
-
GEM_LOAD_MESSAGE = <<-EOS.gsub(/^ {6}/, '')
|
14
|
-
Missing dependency '%s' (version '%s')!
|
15
|
-
EOS
|
16
|
-
|
17
|
-
GEM_INSTALL_COMMAND = <<-EOS.gsub(/^ {6}/, '')
|
18
|
-
Please run the following to satisfy the dependency:
|
19
|
-
gem install --version '%s' %s
|
20
|
-
EOS
|
21
|
-
|
22
|
-
BUNDLER_DECLARE_GEM = <<-EOS.gsub(/^ {6}/, '')
|
23
|
-
Please add the following to your Gemfile to satisfy the dependency:
|
24
|
-
gem '%s', '%s'
|
25
|
-
EOS
|
26
|
-
|
27
|
-
Dependency = Struct.new(:name, :version)
|
28
|
-
|
29
|
-
# The error raised when a dependency can't be loaded.
|
30
|
-
class Error < StandardError; end
|
31
|
-
|
32
|
-
# A list of all loaded dependencies in the dependency manager.
|
33
|
-
@_loaded_dependencies = Set.new
|
34
|
-
|
35
|
-
# class methods
|
36
|
-
class << self
|
37
|
-
|
38
|
-
# Initializes the extended class.
|
39
|
-
#
|
40
|
-
# @param [Class] the class for which some dependencies must be managed
|
41
|
-
#
|
42
|
-
def extended(base)
|
43
|
-
base.class_eval do
|
44
|
-
@_dependencies = Set.new
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Adds a loaded dependency to a list so that it doesn't have
|
49
|
-
# to be loaded again by another classes.
|
50
|
-
#
|
51
|
-
# @param [Dependency] dependency
|
52
|
-
#
|
53
|
-
def add_loaded(dependency)
|
54
|
-
@_loaded_dependencies << dependency
|
55
|
-
end
|
56
|
-
|
57
|
-
# Returns whether the dependency is alread loaded or not.
|
58
|
-
#
|
59
|
-
# @param [Dependency] dependency
|
60
|
-
# @return [Boolean]
|
61
|
-
#
|
62
|
-
def already_loaded?(dependency)
|
63
|
-
@_loaded_dependencies.include?(dependency)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Clears the list of loaded dependencies.
|
67
|
-
#
|
68
|
-
def clear_loaded
|
69
|
-
@_loaded_dependencies.clear
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Registers a new dependency.
|
74
|
-
#
|
75
|
-
# @param [String] name the name of the gem
|
76
|
-
# @param [String] version the version of the gem
|
77
|
-
#
|
78
|
-
def dependency(name, version)
|
79
|
-
@_dependencies << Dependency.new(name, version)
|
80
|
-
end
|
81
|
-
|
82
|
-
# Loads the registered dependencies.
|
83
|
-
#
|
84
|
-
# @raise DependencyManager::Error if the dependency can't be loaded.
|
85
|
-
#
|
86
|
-
def load_depenencies
|
87
|
-
@_dependencies.each do |dependency|
|
88
|
-
begin
|
89
|
-
next if DependencyManager.already_loaded?(dependency)
|
90
|
-
gem(dependency.name, dependency.version)
|
91
|
-
require(dependency.name)
|
92
|
-
DependencyManager.add_loaded(dependency)
|
93
|
-
@_dependencies.delete(dependency)
|
94
|
-
rescue Gem::LoadError
|
95
|
-
args = [dependency.name, dependency.version]
|
96
|
-
command = if running_under_bundler?
|
97
|
-
BUNDLER_DECLARE_GEM % args
|
98
|
-
else
|
99
|
-
GEM_INSTALL_COMMAND % args.reverse
|
100
|
-
end
|
101
|
-
message = GEM_LOAD_MESSAGE % args
|
102
|
-
|
103
|
-
raise Error.new(message + command)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# Returns whether all the dependencies has been loaded or not.
|
109
|
-
#
|
110
|
-
# @return [Boolean]
|
111
|
-
#
|
112
|
-
def dependencies_loaded?
|
113
|
-
@_dependencies.empty?
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
# Returns whether we are running under bundler or not
|
119
|
-
#
|
120
|
-
# @return [Boolean]
|
121
|
-
#
|
122
|
-
def running_under_bundler?
|
123
|
-
!!(File.exists?('Gemfile') && ENV['BUNDLE_GEMFILE'])
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|