activesupport 5.2.4.4 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +353 -435
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/active_support.rb +14 -1
  6. data/lib/active_support/actionable_error.rb +48 -0
  7. data/lib/active_support/array_inquirer.rb +4 -2
  8. data/lib/active_support/backtrace_cleaner.rb +29 -3
  9. data/lib/active_support/benchmarkable.rb +1 -1
  10. data/lib/active_support/cache.rb +142 -78
  11. data/lib/active_support/cache/file_store.rb +33 -33
  12. data/lib/active_support/cache/mem_cache_store.rb +32 -20
  13. data/lib/active_support/cache/memory_store.rb +59 -33
  14. data/lib/active_support/cache/null_store.rb +8 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +70 -43
  16. data/lib/active_support/cache/strategy/local_cache.rb +41 -26
  17. data/lib/active_support/callbacks.rb +81 -64
  18. data/lib/active_support/concern.rb +70 -3
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  20. data/lib/active_support/concurrency/share_lock.rb +0 -1
  21. data/lib/active_support/configurable.rb +10 -14
  22. data/lib/active_support/configuration_file.rb +46 -0
  23. data/lib/active_support/core_ext.rb +1 -1
  24. data/lib/active_support/core_ext/array.rb +1 -1
  25. data/lib/active_support/core_ext/array/access.rb +18 -6
  26. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/benchmark.rb +2 -2
  29. data/lib/active_support/core_ext/class/attribute.rb +32 -47
  30. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  31. data/lib/active_support/core_ext/date/calculations.rb +6 -5
  32. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  33. data/lib/active_support/core_ext/date_and_time/calculations.rb +37 -47
  34. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  35. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  36. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  37. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  38. data/lib/active_support/core_ext/enumerable.rb +171 -75
  39. data/lib/active_support/core_ext/hash.rb +1 -2
  40. data/lib/active_support/core_ext/hash/conversions.rb +3 -3
  41. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  42. data/lib/active_support/core_ext/hash/except.rb +2 -2
  43. data/lib/active_support/core_ext/hash/keys.rb +1 -30
  44. data/lib/active_support/core_ext/hash/slice.rb +6 -27
  45. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  46. data/lib/active_support/core_ext/kernel.rb +0 -1
  47. data/lib/active_support/core_ext/load_error.rb +1 -1
  48. data/lib/active_support/core_ext/marshal.rb +2 -0
  49. data/lib/active_support/core_ext/module.rb +0 -1
  50. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  51. data/lib/active_support/core_ext/module/attribute_accessors.rb +30 -39
  52. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +17 -19
  53. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  54. data/lib/active_support/core_ext/module/delegation.rb +76 -33
  55. data/lib/active_support/core_ext/module/introspection.rb +16 -15
  56. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  57. data/lib/active_support/core_ext/name_error.rb +29 -2
  58. data/lib/active_support/core_ext/numeric.rb +0 -1
  59. data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
  60. data/lib/active_support/core_ext/object/blank.rb +1 -2
  61. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  62. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  63. data/lib/active_support/core_ext/object/json.rb +14 -2
  64. data/lib/active_support/core_ext/object/try.rb +17 -7
  65. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  66. data/lib/active_support/core_ext/range/compare_range.rb +34 -13
  67. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  68. data/lib/active_support/core_ext/range/each.rb +0 -1
  69. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  70. data/lib/active_support/core_ext/regexp.rb +8 -5
  71. data/lib/active_support/core_ext/securerandom.rb +23 -3
  72. data/lib/active_support/core_ext/string/access.rb +5 -16
  73. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  74. data/lib/active_support/core_ext/string/filters.rb +42 -1
  75. data/lib/active_support/core_ext/string/inflections.rb +45 -6
  76. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  77. data/lib/active_support/core_ext/string/multibyte.rb +6 -5
  78. data/lib/active_support/core_ext/string/output_safety.rb +70 -13
  79. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  80. data/lib/active_support/core_ext/string/strip.rb +3 -1
  81. data/lib/active_support/core_ext/symbol.rb +3 -0
  82. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  83. data/lib/active_support/core_ext/time/calculations.rb +50 -3
  84. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  85. data/lib/active_support/core_ext/uri.rb +6 -1
  86. data/lib/active_support/current_attributes.rb +15 -2
  87. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  88. data/lib/active_support/dependencies.rb +109 -34
  89. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  90. data/lib/active_support/deprecation.rb +6 -1
  91. data/lib/active_support/deprecation/behaviors.rb +16 -3
  92. data/lib/active_support/deprecation/disallowed.rb +56 -0
  93. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  94. data/lib/active_support/deprecation/method_wrappers.rb +18 -23
  95. data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
  96. data/lib/active_support/deprecation/reporting.rb +50 -7
  97. data/lib/active_support/descendants_tracker.rb +59 -9
  98. data/lib/active_support/duration.rb +90 -38
  99. data/lib/active_support/duration/iso8601_parser.rb +2 -4
  100. data/lib/active_support/duration/iso8601_serializer.rb +18 -14
  101. data/lib/active_support/encrypted_configuration.rb +0 -4
  102. data/lib/active_support/encrypted_file.rb +22 -4
  103. data/lib/active_support/environment_inquirer.rb +20 -0
  104. data/lib/active_support/evented_file_update_checker.rb +82 -117
  105. data/lib/active_support/execution_wrapper.rb +1 -0
  106. data/lib/active_support/file_update_checker.rb +0 -1
  107. data/lib/active_support/fork_tracker.rb +62 -0
  108. data/lib/active_support/gem_version.rb +4 -4
  109. data/lib/active_support/hash_with_indifferent_access.rb +64 -41
  110. data/lib/active_support/i18n.rb +1 -0
  111. data/lib/active_support/i18n_railtie.rb +15 -8
  112. data/lib/active_support/inflector/inflections.rb +2 -7
  113. data/lib/active_support/inflector/methods.rb +49 -58
  114. data/lib/active_support/inflector/transliterate.rb +47 -18
  115. data/lib/active_support/json/decoding.rb +25 -26
  116. data/lib/active_support/json/encoding.rb +11 -3
  117. data/lib/active_support/key_generator.rb +1 -33
  118. data/lib/active_support/lazy_load_hooks.rb +5 -2
  119. data/lib/active_support/locale/en.rb +33 -0
  120. data/lib/active_support/locale/en.yml +7 -3
  121. data/lib/active_support/log_subscriber.rb +39 -9
  122. data/lib/active_support/logger.rb +2 -17
  123. data/lib/active_support/logger_silence.rb +11 -19
  124. data/lib/active_support/logger_thread_safe_level.rb +50 -6
  125. data/lib/active_support/message_encryptor.rb +8 -13
  126. data/lib/active_support/message_verifier.rb +10 -10
  127. data/lib/active_support/messages/metadata.rb +11 -2
  128. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  129. data/lib/active_support/messages/rotator.rb +10 -9
  130. data/lib/active_support/multibyte/chars.rb +10 -68
  131. data/lib/active_support/multibyte/unicode.rb +15 -327
  132. data/lib/active_support/notifications.rb +72 -8
  133. data/lib/active_support/notifications/fanout.rb +116 -16
  134. data/lib/active_support/notifications/instrumenter.rb +71 -9
  135. data/lib/active_support/number_helper.rb +38 -12
  136. data/lib/active_support/number_helper/number_converter.rb +5 -6
  137. data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
  138. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
  139. data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
  140. data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -3
  141. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  142. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  143. data/lib/active_support/number_helper/number_to_rounded_converter.rb +8 -7
  144. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  145. data/lib/active_support/option_merger.rb +22 -3
  146. data/lib/active_support/ordered_hash.rb +1 -1
  147. data/lib/active_support/ordered_options.rb +13 -3
  148. data/lib/active_support/parameter_filter.rb +133 -0
  149. data/lib/active_support/per_thread_registry.rb +1 -1
  150. data/lib/active_support/rails.rb +1 -10
  151. data/lib/active_support/railtie.rb +23 -1
  152. data/lib/active_support/reloader.rb +4 -5
  153. data/lib/active_support/rescuable.rb +4 -4
  154. data/lib/active_support/secure_compare_rotator.rb +51 -0
  155. data/lib/active_support/security_utils.rb +19 -12
  156. data/lib/active_support/string_inquirer.rb +4 -3
  157. data/lib/active_support/subscriber.rb +72 -28
  158. data/lib/active_support/tagged_logging.rb +42 -8
  159. data/lib/active_support/test_case.rb +91 -0
  160. data/lib/active_support/testing/assertions.rb +30 -9
  161. data/lib/active_support/testing/deprecation.rb +0 -1
  162. data/lib/active_support/testing/file_fixtures.rb +2 -0
  163. data/lib/active_support/testing/isolation.rb +2 -2
  164. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  165. data/lib/active_support/testing/parallelization.rb +51 -0
  166. data/lib/active_support/testing/parallelization/server.rb +78 -0
  167. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  168. data/lib/active_support/testing/stream.rb +1 -2
  169. data/lib/active_support/testing/time_helpers.rb +47 -12
  170. data/lib/active_support/time_with_zone.rb +81 -47
  171. data/lib/active_support/values/time_zone.rb +32 -17
  172. data/lib/active_support/xml_mini.rb +2 -10
  173. data/lib/active_support/xml_mini/jdom.rb +2 -3
  174. data/lib/active_support/xml_mini/libxml.rb +2 -2
  175. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  176. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  177. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  178. data/lib/active_support/xml_mini/rexml.rb +10 -3
  179. metadata +58 -32
  180. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
  181. data/lib/active_support/core_ext/hash/compact.rb +0 -29
  182. data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
  183. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  184. data/lib/active_support/core_ext/module/reachable.rb +0 -11
  185. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
  186. data/lib/active_support/core_ext/range/include_range.rb +0 -3
  187. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -38,10 +38,6 @@ module ActiveSupport
38
38
  @options ||= ActiveSupport::InheritableOptions.new(config)
39
39
  end
40
40
 
41
- def serialize(config)
42
- config.present? ? YAML.dump(config) : ""
43
- end
44
-
45
41
  def deserialize(config)
46
42
  YAML.load(config).presence || {}
47
43
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pathname"
4
+ require "tmpdir"
4
5
  require "active_support/message_encryptor"
5
6
 
6
7
  module ActiveSupport
@@ -19,17 +20,28 @@ module ActiveSupport
19
20
  end
20
21
  end
21
22
 
23
+ class InvalidKeyLengthError < RuntimeError
24
+ def initialize
25
+ super "Encryption key must be exactly #{EncryptedFile.expected_key_length} characters."
26
+ end
27
+ end
28
+
22
29
  CIPHER = "aes-128-gcm"
23
30
 
24
31
  def self.generate_key
25
32
  SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER))
26
33
  end
27
34
 
35
+ def self.expected_key_length # :nodoc:
36
+ @expected_key_length ||= generate_key.length
37
+ end
38
+
28
39
 
29
40
  attr_reader :content_path, :key_path, :env_key, :raise_if_missing_key
30
41
 
31
42
  def initialize(content_path:, key_path:, env_key:, raise_if_missing_key:)
32
- @content_path, @key_path = Pathname.new(content_path), Pathname.new(key_path)
43
+ @content_path = Pathname.new(content_path).yield_self { |path| path.symlink? ? path.realpath : path }
44
+ @key_path = Pathname.new(key_path)
33
45
  @env_key, @raise_if_missing_key = env_key, raise_if_missing_key
34
46
  end
35
47
 
@@ -67,11 +79,12 @@ module ActiveSupport
67
79
 
68
80
  write(updated_contents) if updated_contents != contents
69
81
  ensure
70
- FileUtils.rm(tmp_path) if tmp_path.exist?
82
+ FileUtils.rm(tmp_path) if tmp_path&.exist?
71
83
  end
72
84
 
73
85
 
74
86
  def encrypt(contents)
87
+ check_key_length
75
88
  encryptor.encrypt_and_sign contents
76
89
  end
77
90
 
@@ -89,11 +102,16 @@ module ActiveSupport
89
102
  end
90
103
 
91
104
  def read_key_file
92
- key_path.binread.strip if key_path.exist?
105
+ return @key_file_contents if defined?(@key_file_contents)
106
+ @key_file_contents = (key_path.binread.strip if key_path.exist?)
93
107
  end
94
108
 
95
109
  def handle_missing_key
96
- raise MissingKeyError, key_path: key_path, env_key: env_key if raise_if_missing_key
110
+ raise MissingKeyError.new(key_path: key_path, env_key: env_key) if raise_if_missing_key
111
+ end
112
+
113
+ def check_key_length
114
+ raise InvalidKeyLengthError if key&.length != self.class.expected_key_length
97
115
  end
98
116
  end
99
117
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/string_inquirer"
4
+
5
+ module ActiveSupport
6
+ class EnvironmentInquirer < StringInquirer #:nodoc:
7
+ DEFAULT_ENVIRONMENTS = ["development", "test", "production"]
8
+ def initialize(env)
9
+ super(env)
10
+
11
+ DEFAULT_ENVIRONMENTS.each do |default|
12
+ instance_variable_set :"@#{default}", env == default
13
+ end
14
+ end
15
+
16
+ DEFAULT_ENVIRONMENTS.each do |env|
17
+ class_eval "def #{env}?; @#{env}; end"
18
+ end
19
+ end
20
+ end
@@ -3,6 +3,8 @@
3
3
  require "set"
4
4
  require "pathname"
5
5
  require "concurrent/atomic/atomic_boolean"
6
+ require "listen"
7
+ require "active_support/fork_tracker"
6
8
 
7
9
  module ActiveSupport
8
10
  # Allows you to "listen" to changes in a file system.
@@ -38,48 +40,22 @@ module ActiveSupport
38
40
  raise ArgumentError, "A block is required to initialize an EventedFileUpdateChecker"
39
41
  end
40
42
 
41
- @ph = PathHelper.new
42
- @files = files.map { |f| @ph.xpath(f) }.to_set
43
-
44
- @dirs = {}
45
- dirs.each do |dir, exts|
46
- @dirs[@ph.xpath(dir)] = Array(exts).map { |ext| @ph.normalize_extension(ext) }
47
- end
48
-
49
- @block = block
50
- @updated = Concurrent::AtomicBoolean.new(false)
51
- @lcsp = @ph.longest_common_subpath(@dirs.keys)
52
- @pid = Process.pid
53
- @boot_mutex = Mutex.new
54
-
55
- if (@dtw = directories_to_watch).any?
56
- # Loading listen triggers warnings. These are originated by a legit
57
- # usage of attr_* macros for private attributes, but adds a lot of noise
58
- # to our test suite. Thus, we lazy load it and disable warnings locally.
59
- silence_warnings do
60
- begin
61
- require "listen"
62
- rescue LoadError => e
63
- raise LoadError, "Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile", e.backtrace
64
- end
65
- end
66
- end
67
- boot!
43
+ @block = block
44
+ @core = Core.new(files, dirs)
45
+ ObjectSpace.define_finalizer(self, @core.finalizer)
68
46
  end
69
47
 
70
48
  def updated?
71
- @boot_mutex.synchronize do
72
- if @pid != Process.pid
73
- boot!
74
- @pid = Process.pid
75
- @updated.make_true
76
- end
49
+ if @core.restart?
50
+ @core.thread_safely(&:restart)
51
+ @core.updated.make_true
77
52
  end
78
- @updated.true?
53
+
54
+ @core.updated.true?
79
55
  end
80
56
 
81
57
  def execute
82
- @updated.make_false
58
+ @core.updated.make_false
83
59
  @block.call
84
60
  end
85
61
 
@@ -91,115 +67,104 @@ module ActiveSupport
91
67
  end
92
68
  end
93
69
 
94
- private
95
- def boot!
96
- Listen.to(*@dtw, &method(:changed)).start
97
- end
70
+ class Core
71
+ attr_reader :updated
98
72
 
99
- def changed(modified, added, removed)
100
- unless updated?
101
- @updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
73
+ def initialize(files, dirs)
74
+ @files = files.map { |file| Pathname(file).expand_path }.to_set
75
+
76
+ @dirs = dirs.each_with_object({}) do |(dir, exts), hash|
77
+ hash[Pathname(dir).expand_path] = Array(exts).map { |ext| ext.to_s.sub(/\A\.?/, ".") }.to_set
102
78
  end
103
- end
104
79
 
105
- def watching?(file)
106
- file = @ph.xpath(file)
80
+ @common_path = common_path(@dirs.keys)
107
81
 
108
- if @files.member?(file)
109
- true
110
- elsif file.directory?
111
- false
112
- else
113
- ext = @ph.normalize_extension(file.extname)
82
+ @dtw = directories_to_watch
83
+ @missing = []
114
84
 
115
- file.dirname.ascend do |dir|
116
- if @dirs.fetch(dir, []).include?(ext)
117
- break true
118
- elsif dir == @lcsp || dir.root?
119
- break false
120
- end
121
- end
122
- end
85
+ @updated = Concurrent::AtomicBoolean.new(false)
86
+ @mutex = Mutex.new
87
+
88
+ start
89
+ @after_fork = ActiveSupport::ForkTracker.after_fork { start }
123
90
  end
124
91
 
125
- def directories_to_watch
126
- dtw = (@files + @dirs.keys).map { |f| @ph.existing_parent(f) }
127
- dtw.compact!
128
- dtw.uniq!
92
+ def finalizer
93
+ proc do
94
+ stop
95
+ ActiveSupport::ForkTracker.unregister(@after_fork)
96
+ end
97
+ end
129
98
 
130
- normalized_gem_paths = Gem.path.map { |path| File.join path, "" }
131
- dtw = dtw.reject do |path|
132
- normalized_gem_paths.any? { |gem_path| path.to_s.start_with?(gem_path) }
99
+ def thread_safely
100
+ @mutex.synchronize do
101
+ yield self
133
102
  end
103
+ end
134
104
 
135
- @ph.filter_out_descendants(dtw)
105
+ def start
106
+ normalize_dirs!
107
+ @dtw, @missing = [*@dtw, *@missing].partition(&:exist?)
108
+ @listener = @dtw.any? ? Listen.to(*@dtw, &method(:changed)) : nil
109
+ @listener&.start
136
110
  end
137
111
 
138
- class PathHelper
139
- def xpath(path)
140
- Pathname.new(path).expand_path
141
- end
112
+ def stop
113
+ @listener&.stop
114
+ end
142
115
 
143
- def normalize_extension(ext)
144
- ext.to_s.sub(/\A\./, "")
145
- end
116
+ def restart
117
+ stop
118
+ start
119
+ end
146
120
 
147
- # Given a collection of Pathname objects returns the longest subpath
148
- # common to all of them, or +nil+ if there is none.
149
- def longest_common_subpath(paths)
150
- return if paths.empty?
151
-
152
- lcsp = Pathname.new(paths[0])
153
-
154
- paths[1..-1].each do |path|
155
- until ascendant_of?(lcsp, path)
156
- if lcsp.root?
157
- # If we get here a root directory is not an ascendant of path.
158
- # This may happen if there are paths in different drives on
159
- # Windows.
160
- return
161
- else
162
- lcsp = lcsp.parent
163
- end
164
- end
165
- end
121
+ def restart?
122
+ @missing.any?(&:exist?)
123
+ end
166
124
 
167
- lcsp
125
+ def normalize_dirs!
126
+ @dirs.transform_keys! do |dir|
127
+ dir.exist? ? dir.realpath : dir
168
128
  end
129
+ end
169
130
 
170
- # Returns the deepest existing ascendant, which could be the argument itself.
171
- def existing_parent(dir)
172
- dir.ascend do |ascendant|
173
- break ascendant if ascendant.directory?
174
- end
131
+ def changed(modified, added, removed)
132
+ unless @updated.true?
133
+ @updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
175
134
  end
135
+ end
176
136
 
177
- # Filters out directories which are descendants of others in the collection (stable).
178
- def filter_out_descendants(dirs)
179
- return dirs if dirs.length < 2
137
+ def watching?(file)
138
+ file = Pathname(file)
180
139
 
181
- dirs_sorted_by_nparts = dirs.sort_by { |dir| dir.each_filename.to_a.length }
182
- descendants = []
140
+ if @files.member?(file)
141
+ true
142
+ elsif file.directory?
143
+ false
144
+ else
145
+ ext = file.extname
183
146
 
184
- until dirs_sorted_by_nparts.empty?
185
- dir = dirs_sorted_by_nparts.shift
147
+ file.dirname.ascend do |dir|
148
+ matching = @dirs[dir]
186
149
 
187
- dirs_sorted_by_nparts.reject! do |possible_descendant|
188
- ascendant_of?(dir, possible_descendant) && descendants << possible_descendant
150
+ if matching && (matching.empty? || matching.include?(ext))
151
+ break true
152
+ elsif dir == @common_path || dir.root?
153
+ break false
189
154
  end
190
155
  end
191
-
192
- # Array#- preserves order.
193
- dirs - descendants
194
156
  end
157
+ end
195
158
 
196
- private
159
+ def directories_to_watch
160
+ dtw = @dirs.keys | @files.map(&:dirname)
161
+ accounted_for = dtw.to_set + Gem.path.map { |path| Pathname(path) }
162
+ dtw.reject { |dir| dir.ascend.drop(1).any? { |parent| accounted_for.include?(parent) } }
163
+ end
197
164
 
198
- def ascendant_of?(base, other)
199
- base != other && other.ascend do |ascendant|
200
- break true if base == ascendant
201
- end
202
- end
165
+ def common_path(paths)
166
+ paths.map { |path| path.ascend.to_a }.reduce(&:&)&.first
203
167
  end
168
+ end
204
169
  end
205
170
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/callbacks"
4
+ require "concurrent/hash"
4
5
 
5
6
  module ActiveSupport
6
7
  class ExecutionWrapper
@@ -98,7 +98,6 @@ module ActiveSupport
98
98
  end
99
99
 
100
100
  private
101
-
102
101
  def watched
103
102
  @watched || begin
104
103
  all = @files.select { |f| File.exist?(f) }
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module ForkTracker # :nodoc:
5
+ module CoreExt
6
+ def fork(*)
7
+ if block_given?
8
+ super do
9
+ ForkTracker.check!
10
+ yield
11
+ end
12
+ else
13
+ unless pid = super
14
+ ForkTracker.check!
15
+ end
16
+ pid
17
+ end
18
+ end
19
+ end
20
+
21
+ module CoreExtPrivate
22
+ include CoreExt
23
+
24
+ private
25
+ def fork(*)
26
+ super
27
+ end
28
+ end
29
+
30
+ @pid = Process.pid
31
+ @callbacks = []
32
+
33
+ class << self
34
+ def check!
35
+ if @pid != Process.pid
36
+ @callbacks.each(&:call)
37
+ @pid = Process.pid
38
+ end
39
+ end
40
+
41
+ def hook!
42
+ if Process.respond_to?(:fork)
43
+ ::Object.prepend(CoreExtPrivate)
44
+ ::Kernel.prepend(CoreExtPrivate)
45
+ ::Kernel.singleton_class.prepend(CoreExt)
46
+ ::Process.singleton_class.prepend(CoreExt)
47
+ end
48
+ end
49
+
50
+ def after_fork(&block)
51
+ @callbacks << block
52
+ block
53
+ end
54
+
55
+ def unregister(callback)
56
+ @callbacks.delete(callback)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ ActiveSupport::ForkTracker.hook!
@@ -7,10 +7,10 @@ module ActiveSupport
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 5
11
- MINOR = 2
12
- TINY = 4
13
- PRE = "4"
10
+ MAJOR = 6
11
+ MINOR = 1
12
+ TINY = 1
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end