listen 3.2.1 → 3.3.0.pre.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9a53907593c7c8390f895d361bce34873381883dbd033e02d1706e2e28c13d1
4
- data.tar.gz: 5a8dfdc3c74345e7283b5f5aee13b5ded0f3f44c8fecaf7027551eb2359ecdae
3
+ metadata.gz: 82d32d20751964de477dd8c2ff8af48cc0c70558b323c1043b37d5bf9183c3ba
4
+ data.tar.gz: fb40a33b41e0bf52ce30303fc88a7fb1dd35a9d56e2e920fccf598fcd7193c17
5
5
  SHA512:
6
- metadata.gz: b5cbabed841e265c54aebfff999d306f5a91590e5e5abe8f9867c5ea9e66caa4d952acc7e7b8be10c2f1ea0a77b0ff4a07d653ec45d3009e149b5faa8331a689
7
- data.tar.gz: 76c990e22b861cae3d9c764a290fab1ed90f6547b9c1329c92be797b8d99364ae21cb3367a84e8064e6834c9a3b76ab440a8c597f0dcacae1e06b1991e39c303
6
+ metadata.gz: 14e679e027bb5c100eaf438f10ec96ce5336465366facf7559a19ed6fa23d0c6e89f72eba25fb53a1e689ca08d0572d54399826b3d78d5cb354f2b2c7d105b61
7
+ data.tar.gz: 4b4f93d99b7519d06a7302152e8d86332edb8a656caef7c1b164596d79c221d539ad0a29481709915070945e46fb1c4661bde3368f0e9c55cd277ffe52bc8b13
data/README.md CHANGED
@@ -1,13 +1,14 @@
1
- ## IMPORTANT: If you cannot install Listen (e.g. on Travis/CI builds), [a workaround is here](https://github.com/guard/listen/wiki/Ruby-version-requirements)
2
-
3
- :exclamation: Listen is currently accepting more maintainers. Please [read this](https://github.com/guard/guard/wiki/Maintainers) if you're interested in joining the team.
4
-
5
1
  # Listen
6
2
 
7
- [![Gem Version](https://badge.fury.io/rb/listen.svg)](http://badge.fury.io/rb/listen) [![Build Status](https://travis-ci.org/guard/listen.svg)](https://travis-ci.org/guard/listen) [![Code Climate](https://codeclimate.com/github/guard/listen.svg)](https://codeclimate.com/github/guard/listen) [![Coverage Status](https://coveralls.io/repos/guard/listen/badge.svg?branch=master)](https://coveralls.io/r/guard/listen)
8
-
9
3
  The Listen gem listens to file modifications and notifies you about the changes.
10
4
 
5
+ :exclamation: Listen is currently accepting more maintainers. Please [read this](https://github.com/guard/guard/wiki/Maintainers) if you're interested in joining the team.
6
+
7
+ [![Development Status](https://github.com/guard/listen/workflows/Development/badge.svg)](https://github.com/guard/listen/actions?workflow=Development)
8
+ [![Gem Version](https://badge.fury.io/rb/listen.svg)](http://badge.fury.io/rb/listen)
9
+ [![Code Climate](https://codeclimate.com/github/guard/listen.svg)](https://codeclimate.com/github/guard/listen)
10
+ [![Coverage Status](https://coveralls.io/repos/guard/listen/badge.svg?branch=master)](https://coveralls.io/r/guard/listen)
11
+
11
12
  ## Features
12
13
 
13
14
  * OS-optimized adapters on MRI for Mac OS X 10.6+, Linux, \*BSD and Windows, [more info](#listen-adapters) below.
@@ -1,23 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
4
+ require 'weakref'
2
5
  require 'listen/logger'
3
6
  require 'listen/listener'
4
7
 
5
- require 'listen/internals/thread_pool'
6
-
7
- # Always set up logging by default first time file is required
8
- #
9
- # NOTE: If you need to clear the logger completely, do so *after*
10
- # requiring this file. If you need to set a custom logger,
11
- # require the listen/logger file and set the logger before requiring
12
- # this file.
13
- Listen.setup_default_logger_if_unset
14
-
15
8
  # Won't print anything by default because of level - unless you've set
16
9
  # LISTEN_GEM_DEBUGGING or provided your own logger with a high enough level
17
- Listen::Logger.info "Listen loglevel set to: #{Listen.logger.level}"
18
- Listen::Logger.info "Listen version: #{Listen::VERSION}"
10
+ Listen.logger.info "Listen loglevel set to: #{Listen.logger.level}"
11
+ Listen.logger.info "Listen version: #{Listen::VERSION}"
19
12
 
20
13
  module Listen
14
+ @listeners = Queue.new
15
+
21
16
  class << self
22
17
  # Listens to file system modifications on a either single directory or
23
18
  # multiple directories.
@@ -32,21 +27,21 @@ module Listen
32
27
  # @return [Listen::Listener] the listener
33
28
  #
34
29
  def to(*args, &block)
35
- @listeners ||= []
36
30
  Listener.new(*args, &block).tap do |listener|
37
- @listeners << listener
31
+ @listeners.enq(WeakRef.new(listener))
38
32
  end
39
33
  end
40
34
 
41
35
  # This is used by the `listen` binary to handle Ctrl-C
42
36
  #
43
37
  def stop
44
- Internals::ThreadPool.stop
45
- @listeners ||= []
46
-
47
- # TODO: should use a mutex for this
48
- @listeners.each(&:stop)
49
- @listeners = nil
38
+ while (listener = @listeners.deq(true))
39
+ begin
40
+ listener.stop
41
+ rescue WeakRef::RefError
42
+ end
43
+ end
44
+ rescue ThreadError
50
45
  end
51
46
  end
52
47
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'listen/adapter/base'
2
4
  require 'listen/adapter/bsd'
3
5
  require 'listen/adapter/darwin'
@@ -13,15 +15,15 @@ module Listen
13
15
 
14
16
  class << self
15
17
  def select(options = {})
16
- _log :debug, 'Adapter: considering polling ...'
18
+ Listen.logger.debug 'Adapter: considering polling ...'
17
19
  return Polling if options[:force_polling]
18
- _log :debug, 'Adapter: considering optimized backend...'
20
+ Listen.logger.debug 'Adapter: considering optimized backend...'
19
21
  return _usable_adapter_class if _usable_adapter_class
20
- _log :debug, 'Adapter: falling back to polling...'
22
+ Listen.logger.debug 'Adapter: falling back to polling...'
21
23
  _warn_polling_fallback(options)
22
24
  Polling
23
25
  rescue
24
- _log :warn, format('Adapter: failed: %s:%s', $ERROR_POSITION.inspect,
26
+ Listen.logger.warn format('Adapter: failed: %s:%s', $ERROR_POSITION.inspect,
25
27
  $ERROR_POSITION * "\n")
26
28
  raise
27
29
  end
@@ -36,10 +38,6 @@ module Listen
36
38
  msg = options.fetch(:polling_fallback_message, POLLING_FALLBACK_MESSAGE)
37
39
  Kernel.warn "[Listen warning]:\n #{msg}" if msg
38
40
  end
39
-
40
- def _log(type, message)
41
- Listen::Logger.send(type, message)
42
- end
43
41
  end
44
42
  end
45
43
  end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'listen/options'
2
4
  require 'listen/record'
3
5
  require 'listen/change'
6
+ require 'listen/thread'
4
7
 
5
8
  module Listen
6
9
  module Adapter
@@ -30,7 +33,7 @@ module Listen
30
33
  # TODO: it's a separate method as a temporary workaround for tests
31
34
  def configure
32
35
  if @configured
33
- _log(:warn, 'Adapter already configured!')
36
+ Listen.logger.warn('Adapter already configured!')
34
37
  return
35
38
  end
36
39
 
@@ -63,48 +66,39 @@ module Listen
63
66
  configure
64
67
 
65
68
  if started?
66
- _log(:warn, 'Adapter already started!')
69
+ Listen.logger.warn('Adapter already started!')
67
70
  return
68
71
  end
69
72
 
70
73
  @started = true
71
74
 
72
- calling_stack = caller.dup
73
- Listen::Internals::ThreadPool.add do
74
- begin
75
- @snapshots.values.each do |snapshot|
76
- _timed('Record.build()') { snapshot.record.build }
77
- end
78
- _run
79
- rescue
80
- msg = 'run() in thread failed: %s:\n'\
81
- ' %s\n\ncalled from:\n %s'
82
- _log_exception(msg, calling_stack)
83
- raise # for unit tests mostly
75
+ @run_thread = Listen::Thread.new("run_thread") do
76
+ @snapshots.values.each do |snapshot|
77
+ _timed('Record.build()') { snapshot.record.build }
84
78
  end
79
+ _run
85
80
  end
86
81
  end
87
82
 
88
83
  def stop
89
84
  _stop
90
- end
91
-
92
- def self.usable?
93
- const_get('OS_REGEXP') =~ RbConfig::CONFIG['target_os']
85
+ config.queue.close # this causes queue.pop to return `nil` to the front-end
94
86
  end
95
87
 
96
88
  private
97
89
 
98
90
  def _stop
91
+ @run_thread&.kill
92
+ @run_thread = nil
99
93
  end
100
94
 
101
95
  def _timed(title)
102
96
  start = Time.now.to_f
103
97
  yield
104
98
  diff = Time.now.to_f - start
105
- Listen::Logger.info format('%s: %.05f seconds', title, diff)
99
+ Listen.logger.info format('%s: %.05f seconds', title, diff)
106
100
  rescue
107
- Listen::Logger.warn "#{title} crashed: #{$ERROR_INFO.inspect}"
101
+ Listen.logger.warn "#{title} crashed: #{$ERROR_INFO.inspect}"
108
102
  raise
109
103
  end
110
104
 
@@ -114,10 +108,6 @@ module Listen
114
108
  @snapshots[dir].invalidate(type, rel_path, options)
115
109
  end
116
110
 
117
- def _log(*args, &block)
118
- self.class.send(:_log, *args, &block)
119
- end
120
-
121
111
  def _log_exception(msg, caller_stack)
122
112
  formatted = format(
123
113
  msg,
@@ -126,14 +116,12 @@ module Listen
126
116
  caller_stack * "\n"
127
117
  )
128
118
 
129
- _log(:error, formatted)
119
+ Listen.logger.error(formatted)
130
120
  end
131
121
 
132
122
  class << self
133
- private
134
-
135
- def _log(*args, &block)
136
- Listen::Logger.send(*args, &block)
123
+ def usable?
124
+ const_get('OS_REGEXP') =~ RbConfig::CONFIG['target_os']
137
125
  end
138
126
  end
139
127
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Listener implementation for BSD's `kqueue`.
2
4
  # @see http://www.freebsd.org/cgi/man.cgi?query=kqueue
3
5
  # @see https://github.com/mat813/rb-kqueue/blob/master/lib/rb-kqueue/queue.rb
@@ -94,7 +96,7 @@ module Listen
94
96
  def _watch_file(path, queue)
95
97
  queue.watch_file(path, *options.events, &@callback)
96
98
  rescue Errno::ENOENT => e
97
- _log :warn, "kqueue: watch file failed: #{e.message}"
99
+ Listen.logger.warn "kqueue: watch file failed: #{e.message}"
98
100
  end
99
101
 
100
102
  # Quick rubocop workaround
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
 
3
5
  module Listen
@@ -1,12 +1,13 @@
1
- require 'thread'
2
- require 'listen/internals/thread_pool'
1
+ # frozen_string_literal: true
2
+
3
+ require 'listen/thread'
3
4
 
4
5
  module Listen
5
6
  module Adapter
6
7
  # Adapter implementation for Mac OS X `FSEvents`.
7
8
  #
8
9
  class Darwin < Base
9
- OS_REGEXP = /darwin(?<major_version>1\d+)/i
10
+ OS_REGEXP = /darwin(?<major_version>(1|2)\d+)/i
10
11
 
11
12
  # The default delay between checking for changes.
12
13
  DEFAULTS = { latency: 0.1 }.freeze
@@ -43,9 +44,9 @@ module Listen
43
44
  require 'rb-fsevent'
44
45
  worker = FSEvent.new
45
46
  dirs_to_watch = @callbacks.keys.map(&:to_s)
46
- _log(:info) { "fsevent: watching: #{dirs_to_watch.inspect}" }
47
+ Listen.logger.info { "fsevent: watching: #{dirs_to_watch.inspect}" }
47
48
  worker.watch(dirs_to_watch, { latency: options.latency }, &method(:_process_changes))
48
- Listen::Internals::ThreadPool.add { _run_worker(worker) }
49
+ @worker_thread = Listen::Thread.new("worker_thread") { worker.run }
49
50
  end
50
51
 
51
52
  def _process_changes(dirs)
@@ -61,18 +62,15 @@ module Listen
61
62
  end
62
63
 
63
64
  def _process_event(dir, path)
64
- _log(:debug) { "fsevent: processing path: #{path.inspect}" }
65
+ Listen.logger.debug { "fsevent: processing path: #{path.inspect}" }
65
66
  # TODO: does this preserve symlinks?
66
67
  rel_path = path.relative_path_from(dir).to_s
67
68
  _queue_change(:dir, dir, rel_path, recursive: true)
68
69
  end
69
70
 
70
- def _run_worker(worker)
71
- _log(:debug) { "fsevent: running worker: #{worker.inspect}" }
72
- worker.run
73
- rescue
74
- format_string = 'fsevent: running worker failed: %s:%s called from: %s'
75
- _log_exception format_string, caller
71
+ def _stop
72
+ @worker_thread&.kill
73
+ super
76
74
  end
77
75
  end
78
76
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Listen
2
4
  module Adapter
3
5
  # @see https://github.com/nex3/rb-inotify
@@ -35,9 +37,7 @@ module Listen
35
37
  end
36
38
 
37
39
  def _run
38
- Thread.current[:listen_blocking_read_thread] = true
39
40
  @worker.run
40
- Thread.current[:listen_blocking_read_thread] = false
41
41
  end
42
42
 
43
43
  def _process_event(dir, event)
@@ -47,7 +47,7 @@ module Listen
47
47
  path = Pathname.new(event.watcher.path) + event.name
48
48
  rel_path = path.relative_path_from(dir).to_s
49
49
 
50
- _log(:debug) { "inotify: #{rel_path} (#{event.flags.inspect})" }
50
+ Listen.logger.debug { "inotify: #{rel_path} (#{event.flags.inspect})" }
51
51
 
52
52
  if /1|true/ =~ ENV['LISTEN_GEM_SIMULATE_FSEVENT']
53
53
  if (event.flags & [:moved_to, :moved_from]) || _dir_event?(event)
@@ -99,7 +99,9 @@ module Listen
99
99
  end
100
100
 
101
101
  def _stop
102
- @worker && @worker.close
102
+ @worker&.close
103
+
104
+ super
103
105
  end
104
106
  end
105
107
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Listen
2
4
  module Adapter
3
5
  # Polling Adapter that works cross-platform and
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Listen
2
4
  module Adapter
3
5
  # Adapter implementation for Windows `wdm`.
@@ -15,7 +17,7 @@ module Listen
15
17
  require 'wdm'
16
18
  true
17
19
  rescue LoadError
18
- _log :debug, format('wdm - load failed: %s:%s', $ERROR_INFO,
20
+ Listen.logger.debug format('wdm - load failed: %s:%s', $ERROR_INFO,
19
21
  $ERROR_POSITION * "\n")
20
22
 
21
23
  Kernel.warn BUNDLER_DECLARE_GEM
@@ -26,7 +28,7 @@ module Listen
26
28
 
27
29
  def _configure(dir)
28
30
  require 'wdm'
29
- _log :debug, 'wdm - starting...'
31
+ Listen.logger.debug 'wdm - starting...'
30
32
  @worker ||= WDM::Monitor.new
31
33
  @worker.watch_recursively(dir.to_s, :files) do |change|
32
34
  yield([:file, change])
@@ -47,7 +49,7 @@ module Listen
47
49
  end
48
50
 
49
51
  def _process_event(dir, event)
50
- _log :debug, "wdm - callback: #{event.inspect}"
52
+ Listen.logger.debug "wdm - callback: #{event.inspect}"
51
53
 
52
54
  type, change = event
53
55
 
@@ -80,7 +82,7 @@ module Listen
80
82
  end
81
83
  rescue
82
84
  details = event.inspect
83
- _log :error, format('wdm - callback (%s): %s:%s', details, $ERROR_INFO,
85
+ Listen.logger.error format('wdm - callback (%s): %s:%s', details, $ERROR_INFO,
84
86
  $ERROR_POSITION * "\n")
85
87
  raise
86
88
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'listen/adapter'
2
4
  require 'listen/adapter/base'
3
5
  require 'listen/adapter/config'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'listen/file'
2
4
  require 'listen/directory'
3
5
 
@@ -35,13 +37,13 @@ module Listen
35
37
  cookie = options[:cookie]
36
38
 
37
39
  if !cookie && config.silenced?(rel_path, type)
38
- Listen::Logger.debug { "(silenced): #{rel_path.inspect}" }
40
+ Listen.logger.debug { "(silenced): #{rel_path.inspect}" }
39
41
  return
40
42
  end
41
43
 
42
44
  path = watched_dir + rel_path
43
45
 
44
- Listen::Logger.debug do
46
+ Listen.logger.debug do
45
47
  log_details = options[:silence] && 'recording' || change || 'unknown'
46
48
  "#{log_details}: #{type}:#{path} (#{options.inspect})"
47
49
  end
@@ -65,7 +67,7 @@ module Listen
65
67
  __method__,
66
68
  exinspect,
67
69
  ex.backtrace * "\n")
68
- Listen::Logger.error(msg)
70
+ Listen.logger.error(msg)
69
71
  raise
70
72
  end
71
73
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
  require 'listen'
3
5
  require 'logger'
@@ -35,8 +37,7 @@ module Listen
35
37
  attr_reader :logger
36
38
  def initialize(options)
37
39
  @options = options
38
- @logger = ::Logger.new(STDOUT)
39
- @logger.level = ::Logger::INFO
40
+ @logger = ::Logger.new(STDOUT, level: ::Logger::INFO)
40
41
  @logger.formatter = proc { |_, _, _, msg| "#{msg}\n" }
41
42
  end
42
43
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
2
4
 
3
5
  module Listen
@@ -14,7 +16,7 @@ module Listen
14
16
  path = dir + rel_path
15
17
  current = Set.new(_children(path))
16
18
 
17
- Listen::Logger.debug do
19
+ Listen.logger.debug do
18
20
  format('%s: %s(%s): %s -> %s',
19
21
  (options[:silence] ? 'Recording' : 'Scanning'),
20
22
  rel_path, options.inspect, previous.inspect, current.inspect)
@@ -47,7 +49,7 @@ module Listen
47
49
  _async_changes(snapshot, path, previous, options)
48
50
  _change(snapshot, :file, rel_path, options)
49
51
  rescue
50
- Listen::Logger.warn do
52
+ Listen.logger.warn do
51
53
  format('scan DIED: %s:%s', $ERROR_INFO, $ERROR_POSITION * "\n")
52
54
  end
53
55
  raise