listen 3.0.8 → 3.5.1

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.
data/lib/listen/record.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thread'
2
4
  require 'listen/record/entry'
3
5
  require 'listen/record/symlink_detector'
@@ -8,14 +10,16 @@ module Listen
8
10
  # TODO: deprecate
9
11
 
10
12
  attr_reader :root
13
+
11
14
  def initialize(directory)
12
15
  @tree = _auto_hash
13
16
  @root = directory.to_s
14
17
  end
15
18
 
16
19
  def add_dir(rel_path)
17
- return if [nil, '', '.'].include? rel_path
18
- @tree[rel_path] ||= {}
20
+ if ![nil, '', '.'].include?(rel_path)
21
+ @tree[rel_path] ||= {}
22
+ end
19
23
  end
20
24
 
21
25
  def update_file(rel_path, data)
@@ -31,30 +35,27 @@ module Listen
31
35
  def file_data(rel_path)
32
36
  dirname, basename = Pathname(rel_path).split.map(&:to_s)
33
37
  if [nil, '', '.'].include? dirname
34
- tree[basename] ||= {}
35
- tree[basename].dup
38
+ @tree[basename] ||= {}
39
+ @tree[basename].dup
36
40
  else
37
- tree[dirname] ||= {}
38
- tree[dirname][basename] ||= {}
39
- tree[dirname][basename].dup
41
+ @tree[dirname] ||= {}
42
+ @tree[dirname][basename] ||= {}
43
+ @tree[dirname][basename].dup
40
44
  end
41
45
  end
42
46
 
43
47
  def dir_entries(rel_path)
44
- subtree =
45
- if [nil, '', '.'].include? rel_path.to_s
46
- tree
47
- else
48
- tree[rel_path.to_s] ||= _auto_hash
49
- tree[rel_path.to_s]
50
- end
48
+ subtree = if ['', '.'].include? rel_path.to_s
49
+ @tree
50
+ else
51
+ @tree[rel_path.to_s] ||= _auto_hash
52
+ @tree[rel_path.to_s]
53
+ end
51
54
 
52
- result = {}
53
- subtree.each do |key, values|
55
+ subtree.transform_values do |values|
54
56
  # only get data for file entries
55
- result[key] = values.key?(:mtime) ? values : {}
57
+ values.key?(:mtime) ? values : {}
56
58
  end
57
- result
58
59
  end
59
60
 
60
61
  def build
@@ -71,31 +72,27 @@ module Listen
71
72
  private
72
73
 
73
74
  def _auto_hash
74
- Hash.new { |h, k| h[k] = Hash.new }
75
- end
76
-
77
- def tree
78
- @tree
75
+ Hash.new { |h, k| h[k] = {} }
79
76
  end
80
77
 
81
78
  def _fast_update_file(dirname, basename, data)
82
- if [nil, '', '.'].include? dirname
83
- tree[basename] = (tree[basename] || {}).merge(data)
79
+ if [nil, '', '.'].include?(dirname)
80
+ @tree[basename] = (@tree[basename] || {}).merge(data)
84
81
  else
85
- tree[dirname] ||= {}
86
- tree[dirname][basename] = (tree[dirname][basename] || {}).merge(data)
82
+ @tree[dirname] ||= {}
83
+ @tree[dirname][basename] = (@tree[dirname][basename] || {}).merge(data)
87
84
  end
88
85
  end
89
86
 
90
87
  def _fast_unset_path(dirname, basename)
91
88
  # this may need to be reworked to properly remove
92
89
  # entries from a tree, without adding non-existing dirs to the record
93
- if [nil, '', '.'].include? dirname
94
- return unless tree.key?(basename)
95
- tree.delete(basename)
96
- else
97
- return unless tree.key?(dirname)
98
- tree[dirname].delete(basename)
90
+ if [nil, '', '.'].include?(dirname)
91
+ if @tree.key?(basename)
92
+ @tree.delete(basename)
93
+ end
94
+ elsif @tree.key?(dirname)
95
+ @tree[dirname].delete(basename)
99
96
  end
100
97
  end
101
98
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Listen
2
4
  class Silencer
3
5
  class Controller
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Listen
2
4
  class Silencer
3
5
  # The default list of directories that get ignored.
@@ -12,10 +14,10 @@ module Listen
12
14
  | log
13
15
  | tmp
14
16
  |vendor/ruby
15
- )(/|$)}x
17
+ )(/|$)}x.freeze
16
18
 
17
19
  # The default list of files that get ignored.
18
- DEFAULT_IGNORED_EXTENSIONS = /(?:
20
+ DEFAULT_IGNORED_EXTENSIONS = %r{(?:
19
21
  # Kate's tmp\/swp files
20
22
  \..*\d+\.new
21
23
  | \.kate-swp
@@ -46,11 +48,14 @@ module Listen
46
48
  )
47
49
  )
48
50
 
51
+ # Mutagen sync temporary files
52
+ | \.mutagen-temporary.*
53
+
49
54
  # other files
50
55
  | \.DS_Store
51
56
  | \.tmp
52
57
  | ~
53
- )$/x
58
+ )$}x.freeze
54
59
 
55
60
  attr_accessor :only_patterns, :ignore_patterns
56
61
 
@@ -70,16 +75,18 @@ module Listen
70
75
  def silenced?(relative_path, type)
71
76
  path = relative_path.to_s
72
77
 
73
- if only_patterns && type == :file
74
- return true unless only_patterns.any? { |pattern| path =~ pattern }
75
- end
76
-
77
- ignore_patterns.any? { |pattern| path =~ pattern }
78
+ _ignore?(path) || (only_patterns && type == :file && !_only?(path))
78
79
  end
79
80
 
80
81
  private
81
82
 
82
- attr_reader :options
83
+ def _ignore?(path)
84
+ ignore_patterns.any? { |pattern| path =~ pattern }
85
+ end
86
+
87
+ def _only?(path)
88
+ only_patterns.any? { |pattern| path =~ pattern }
89
+ end
83
90
 
84
91
  def _init_ignores(ignores, overrides)
85
92
  patterns = []
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thread'
4
+
5
+ require_relative 'logger'
6
+
7
+ module Listen
8
+ module Thread
9
+ class << self
10
+ # Creates a new thread with the given name.
11
+ # Any exceptions raised by the thread will be logged with the thread name and complete backtrace.
12
+ # rubocop:disable Style/MultilineBlockChain
13
+ def new(name, &block)
14
+ thread_name = "listen-#{name}"
15
+ caller_stack = caller
16
+
17
+ ::Thread.new do
18
+ rescue_and_log(thread_name, caller_stack: caller_stack, &block)
19
+ end.tap do |thread|
20
+ thread.name = thread_name
21
+ end
22
+ end
23
+ # rubocop:enable Style/MultilineBlockChain
24
+
25
+ def rescue_and_log(method_name, *args, caller_stack: nil)
26
+ yield(*args)
27
+ rescue => exception
28
+ _log_exception(exception, method_name, caller_stack: caller_stack)
29
+ end
30
+
31
+ private
32
+
33
+ def _log_exception(exception, thread_name, caller_stack: nil)
34
+ complete_backtrace = if caller_stack
35
+ [*exception.backtrace, "--- Thread.new ---", *caller_stack]
36
+ else
37
+ exception.backtrace
38
+ end
39
+ message = "Exception rescued in #{thread_name}:\n#{_exception_with_causes(exception)}\n#{complete_backtrace * "\n"}"
40
+ Listen.logger.error(message)
41
+ end
42
+
43
+ def _exception_with_causes(exception)
44
+ result = +"#{exception.class}: #{exception}"
45
+ if exception.cause
46
+ result << "\n"
47
+ result << "--- Caused by: ---\n"
48
+ result << _exception_with_causes(exception.cause)
49
+ end
50
+ result
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Listen
2
- VERSION = '3.0.8'
4
+ VERSION = '3.5.1'
3
5
  end
data/lib/listen.rb CHANGED
@@ -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,24 +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 do |listener|
49
- # call stop to halt the main loop
50
- listener.stop
38
+ while (listener = @listeners.deq(true))
39
+ begin
40
+ listener.stop
41
+ rescue WeakRef::RefError
42
+ end
51
43
  end
52
- @listeners = nil
44
+ rescue ThreadError
53
45
  end
54
46
  end
55
47
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: listen
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.8
4
+ version: 3.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thibaud Guillaume-Gentil
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-18 00:00:00.000000000 Z
11
+ date: 2021-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb-fsevent
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.9'
19
+ version: '0.10'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 0.9.4
22
+ version: 0.10.3
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '0.9'
29
+ version: '0.10'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 0.9.4
32
+ version: 0.10.3
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rb-inotify
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +39,7 @@ dependencies:
39
39
  version: '0.9'
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 0.9.7
42
+ version: 0.9.10
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,21 +49,7 @@ dependencies:
49
49
  version: '0.9'
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 0.9.7
53
- - !ruby/object:Gem::Dependency
54
- name: bundler
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - ">="
58
- - !ruby/object:Gem::Version
59
- version: 1.3.5
60
- type: :development
61
- prerelease: false
62
- version_requirements: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- version: 1.3.5
52
+ version: 0.9.10
67
53
  description: The Listen gem listens to file modifications and notifies you about the
68
54
  changes. Works everywhere!
69
55
  email: thibaud@thibaud.gg
@@ -90,16 +76,17 @@ files:
90
76
  - lib/listen/change.rb
91
77
  - lib/listen/cli.rb
92
78
  - lib/listen/directory.rb
79
+ - lib/listen/error.rb
93
80
  - lib/listen/event/config.rb
94
81
  - lib/listen/event/loop.rb
95
82
  - lib/listen/event/processor.rb
96
83
  - lib/listen/event/queue.rb
97
84
  - lib/listen/file.rb
98
85
  - lib/listen/fsm.rb
99
- - lib/listen/internals/thread_pool.rb
100
86
  - lib/listen/listener.rb
101
87
  - lib/listen/listener/config.rb
102
88
  - lib/listen/logger.rb
89
+ - lib/listen/monotonic_time.rb
103
90
  - lib/listen/options.rb
104
91
  - lib/listen/queue_optimizer.rb
105
92
  - lib/listen/record.rb
@@ -107,11 +94,18 @@ files:
107
94
  - lib/listen/record/symlink_detector.rb
108
95
  - lib/listen/silencer.rb
109
96
  - lib/listen/silencer/controller.rb
97
+ - lib/listen/thread.rb
110
98
  - lib/listen/version.rb
111
99
  homepage: https://github.com/guard/listen
112
100
  licenses:
113
101
  - MIT
114
- metadata: {}
102
+ metadata:
103
+ allowed_push_host: https://rubygems.org
104
+ bug_tracker_uri: https://github.com/guard/listen/issues
105
+ changelog_uri: https://github.com/guard/listen/releases
106
+ documentation_uri: https://www.rubydoc.info/gems/listen/3.5.1
107
+ homepage_uri: https://github.com/guard/listen
108
+ source_code_uri: https://github.com/guard/listen/tree/v3.5.1
115
109
  post_install_message:
116
110
  rdoc_options: []
117
111
  require_paths:
@@ -120,17 +114,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
120
114
  requirements:
121
115
  - - ">="
122
116
  - !ruby/object:Gem::Version
123
- version: 1.9.3
117
+ version: 2.4.0
124
118
  required_rubygems_version: !ruby/object:Gem::Requirement
125
119
  requirements:
126
120
  - - ">="
127
121
  - !ruby/object:Gem::Version
128
122
  version: '0'
129
123
  requirements: []
130
- rubyforge_project:
131
- rubygems_version: 2.5.1
124
+ rubygems_version: 3.0.1
132
125
  signing_key:
133
126
  specification_version: 4
134
127
  summary: Listen to file modifications
135
128
  test_files: []
136
- has_rdoc:
@@ -1,29 +0,0 @@
1
- module Listen
2
- # @private api
3
- module Internals
4
- module ThreadPool
5
- def self.add(&block)
6
- Thread.new { block.call }.tap do |th|
7
- (@threads ||= Queue.new) << th
8
- end
9
- end
10
-
11
- def self.stop
12
- return unless @threads ||= nil
13
- return if @threads.empty? # return to avoid using possibly stubbed Queue
14
-
15
- killed = Queue.new
16
- # You can't kill a read on a descriptor in JRuby, so let's just
17
- # ignore running threads (listen rb-inotify waiting for disk activity
18
- # before closing) pray threads die faster than they are created...
19
- limit = RUBY_ENGINE == 'jruby' ? [1] : []
20
-
21
- killed << @threads.pop.kill until @threads.empty?
22
- until killed.empty?
23
- th = killed.pop
24
- th.join(*limit) unless th[:listen_blocking_read_thread]
25
- end
26
- end
27
- end
28
- end
29
- end